Remove obsolete GLES3 backend

Due to the port to Vulkan and complete redesign of the rendering backend,
the `drivers/gles3` code is no longer usable in this state and is not
planned to be ported to the new architecture.

The GLES2 backend is kept (while still disabled and non-working) as it
will eventually be ported to serve as the low-end renderer for Godot 4.0.

Some GLES3 features might be selectively ported to the updated GLES2
backend if there's a need for them, and extensions we can use for that.

So long, OpenGL driver bugs!
This commit is contained in:
Rémi Verschelde 2020-02-13 10:08:52 +01:00
parent d661ca5357
commit 386968ea97
82 changed files with 97 additions and 27728 deletions

View file

@ -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')})

View file

@ -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);

View file

@ -104,7 +104,6 @@ protected:
public:
enum VideoDriver {
VIDEO_DRIVER_GLES3,
VIDEO_DRIVER_GLES2,
VIDEO_DRIVER_VULKAN,
};

View file

@ -534,7 +534,7 @@
Set [code]ALBEDO[/code] to the per-vertex color specified in the mesh.
</constant>
<constant name="FLAG_SRGB_VERTEX_COLOR" value="2" enum="Flags">
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.
</constant>
<constant name="FLAG_USE_POINT_SIZE" value="3" enum="Flags">
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].

View file

@ -295,9 +295,6 @@
</member>
</members>
<constants>
<constant name="gray" value="Color( 0.75, 0.75, 0.75, 1 )">
Gray color.
</constant>
<constant name="aliceblue" value="Color( 0.94, 0.97, 1, 1 )">
Alice blue color.
</constant>
@ -448,6 +445,9 @@
<constant name="goldenrod" value="Color( 0.85, 0.65, 0.13, 1 )">
Goldenrod color.
</constant>
<constant name="gray" value="Color( 0.75, 0.75, 0.75, 1 )">
Gray color.
</constant>
<constant name="green" value="Color( 0, 1, 0, 1 )">
Green color.
</constant>

View file

@ -619,7 +619,7 @@
</description>
</method>
<method name="rpc_config">
<return type="void">
<return type="int">
</return>
<argument index="0" name="method" type="String">
</argument>
@ -672,7 +672,7 @@
</description>
</method>
<method name="rset_config">
<return type="void">
<return type="int">
</return>
<argument index="0" name="property" type="String">
</argument>

View file

@ -973,11 +973,11 @@
</member>
</members>
<constants>
<constant name="VIDEO_DRIVER_GLES2" value="1" enum="VideoDriver">
<constant name="VIDEO_DRIVER_GLES2" value="0" enum="VideoDriver">
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.
</constant>
<constant name="VIDEO_DRIVER_GLES3" value="0" enum="VideoDriver">
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.
<constant name="VIDEO_DRIVER_VULKAN" value="1" enum="VideoDriver">
The Vulkan rendering backend.
</constant>
<constant name="DAY_SUNDAY" value="0" enum="Weekday">
Sunday.

View file

@ -89,7 +89,7 @@
The amount of vertex memory used.
</constant>
<constant name="RENDER_USAGE_VIDEO_MEM_TOTAL" value="21" enum="Monitor">
Unimplemented in the GLES2 and GLES3 rendering backends, always returns 0.
Unimplemented in the GLES2 rendering backend, always returns 0.
</constant>
<constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="22" enum="Monitor">
Number of active [RigidBody2D] nodes in the game.

View file

@ -972,7 +972,7 @@
</member>
<member name="rendering/quality/2d/gles2_use_nvidia_rect_flicker_workaround" type="bool" setter="" getter="" default="false">
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.
</member>
<member name="rendering/quality/2d/use_pixel_snap" type="bool" setter="" getter="" default="false">
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.
</member>
<member name="rendering/quality/driver/driver_name" type="String" setter="" getter="" default="&quot;Vulkan&quot;">
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.
</member>
<member name="rendering/quality/driver/fallback_to_gles2" type="bool" setter="" getter="" default="false">
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.
</member>
<member name="rendering/quality/filters/depth_of_field_bokeh_quality" type="int" setter="" getter="" default="2">
</member>
@ -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.
</member>
<member name="rendering/vram_compression/import_bptc" type="bool" setter="" getter="" default="false">
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.
</member>
<member name="rendering/vram_compression/import_etc" type="bool" setter="" getter="" default="false">
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.
</member>
<member name="rendering/vram_compression/import_etc2" type="bool" setter="" getter="" default="true">
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.
</member>
<member name="rendering/vram_compression/import_pvrtc" type="bool" setter="" getter="" default="false">
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.

View file

@ -3706,7 +3706,7 @@
The amount of draw calls in frame.
</constant>
<constant name="INFO_USAGE_VIDEO_MEM_TOTAL" value="6" enum="RenderInfo">
Unimplemented in the GLES2 and GLES3 rendering backends, always returns 0.
Unimplemented in the GLES2 rendering backend, always returns 0.
</constant>
<constant name="INFO_VIDEO_MEM_USED" value="7" enum="RenderInfo">
The amount of video memory used, i.e. texture and vertex memory combined.

View file

@ -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')

View file

@ -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;

View file

@ -99,4 +99,4 @@ public:
ShaderCompilerGLES2();
};
#endif // SHADERCOMPILERGLES3_H
#endif // SHADERCOMPILERGLES2_H

View file

@ -1,7 +0,0 @@
#!/usr/bin/env python
Import('env')
env.add_source_files(env.drivers_sources,"*.cpp")
SConscript("shaders/SCsub")

File diff suppressed because it is too large Load diff

View file

@ -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<LightInternal> 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

View file

@ -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<Image> &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);
}

View file

@ -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<Image> &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

File diff suppressed because it is too large Load diff

View file

@ -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<RasterizerStorageGLES3::RenderTarget::Exposure> 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<Shadow> shadows;
Quadrant() {
subdivision = 0; //not in use
}
} quadrants[4];
int size_order[4];
uint32_t smallest_subdiv;
int size;
GLuint fbo;
GLuint depth;
Map<RID, uint32_t> shadow_owners;
};
struct ShadowCubeMap {
GLuint fbo_id[6];
GLuint cubemap;
uint32_t size;
};
Vector<ShadowCubeMap> shadow_cubemaps;
RID_PtrOwner<ShadowAtlas> 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<Reflection> reflections;
};
mutable RID_PtrOwner<ReflectionAtlas> 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<ReflectionCubeMap> 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<ReflectionProbeInstance> 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> 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<RID> shadow_atlases; //shadow atlases where this light is registered
LightInstance() {}
};
mutable RID_PtrOwner<LightInstance> 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<GIProbeInstance> 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<Element *, SortByKey> 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<Element *, SortByDepth> 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<Element *, SortByReverseDepthAndPriority> 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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,109 +0,0 @@
/*************************************************************************/
/* shader_compiler_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 SHADERCOMPILERGLES3_H
#define SHADERCOMPILERGLES3_H
#include "core/pair.h"
#include "servers/visual/shader_language.h"
#include "servers/visual/shader_types.h"
#include "servers/visual_server.h"
class ShaderCompilerGLES3 {
public:
struct IdentifierActions {
Map<StringName, Pair<int *, int> > render_mode_values;
Map<StringName, bool *> render_mode_flags;
Map<StringName, bool *> usage_flag_pointers;
Map<StringName, bool *> write_flag_pointers;
Map<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms;
};
struct GeneratedCode {
Vector<CharString> defines;
struct Texture {
StringName name;
ShaderLanguage::DataType type;
ShaderLanguage::ShaderNode::Uniform::Hint hint;
ShaderLanguage::ShaderNode::Uniform::Filter filter;
ShaderLanguage::ShaderNode::Uniform::Repeat repeat;
};
Vector<Texture> texture_uniforms;
Vector<uint32_t> uniform_offsets;
uint32_t uniform_total_size;
String uniforms;
String vertex_global;
String vertex;
String fragment_global;
String fragment;
String light;
bool uses_fragment_time;
bool uses_vertex_time;
};
private:
ShaderLanguage parser;
struct DefaultIdentifierActions {
Map<StringName, String> renames;
Map<StringName, String> render_mode_defines;
Map<StringName, String> usage_defines;
};
void _dump_function_deps(ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added);
String _dump_node_code(ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning);
StringName current_func_name;
StringName vertex_name;
StringName fragment_name;
StringName light_name;
StringName time_name;
Set<StringName> used_name_defines;
Set<StringName> used_flag_pointers;
Set<StringName> used_rmode_defines;
Set<StringName> internal_functions;
DefaultIdentifierActions actions[VS::SHADER_MAX];
public:
Error compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code);
ShaderCompilerGLES3();
};
#endif // SHADERCOMPILERGLES3_H

View file

@ -1,777 +0,0 @@
/*************************************************************************/
/* shader_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 "shader_gles3.h"
#include "core/print_string.h"
//#define DEBUG_OPENGL
#ifdef DEBUG_OPENGL
#define DEBUG_TEST_ERROR(m_section) \
{ \
uint32_t err = glGetError(); \
if (err) { \
print_line("OpenGL Error #" + itos(err) + " at: " + m_section); \
} \
}
#else
#define DEBUG_TEST_ERROR(m_section)
#endif
ShaderGLES3 *ShaderGLES3::active = NULL;
//#define DEBUG_SHADER
#ifdef DEBUG_SHADER
#define DEBUG_PRINT(m_text) print_line(m_text);
#else
#define DEBUG_PRINT(m_text)
#endif
void ShaderGLES3::bind_uniforms() {
if (!uniforms_dirty) {
return;
};
// upload default uniforms
const Map<uint32_t, Variant>::Element *E = uniform_defaults.front();
while (E) {
int idx = E->key();
int location = version->uniform_location[idx];
if (location < 0) {
E = E->next();
continue;
}
const Variant &v = E->value();
_set_uniform_variant(location, v);
//print_line("uniform "+itos(location)+" value "+v+ " type "+Variant::get_type_name(v.get_type()));
E = E->next();
};
const Map<uint32_t, CameraMatrix>::Element *C = uniform_cameras.front();
while (C) {
int location = version->uniform_location[C->key()];
if (location < 0) {
C = C->next();
continue;
}
glUniformMatrix4fv(location, 1, false, &(C->get().matrix[0][0]));
C = C->next();
};
uniforms_dirty = false;
}
GLint ShaderGLES3::get_uniform_location(int p_index) const {
ERR_FAIL_COND_V(!version, -1);
return version->uniform_location[p_index];
}
bool ShaderGLES3::bind() {
if (active != this || !version || new_conditional_version.key != conditional_version.key) {
conditional_version = new_conditional_version;
version = get_current_version();
} else {
return false;
}
ERR_FAIL_COND_V(!version, false);
if (!version->ok) { //broken, unable to bind (do not throw error, you saw it before already when it failed compilation).
glUseProgram(0);
return false;
}
glUseProgram(version->id);
DEBUG_TEST_ERROR("Use Program");
active = this;
uniforms_dirty = true;
return true;
}
void ShaderGLES3::unbind() {
version = NULL;
glUseProgram(0);
uniforms_dirty = true;
active = NULL;
}
static void _display_error_with_code(const String &p_error, const Vector<const char *> &p_code) {
int line = 1;
String total_code;
for (int i = 0; i < p_code.size(); i++) {
total_code += String(p_code[i]);
}
Vector<String> lines = String(total_code).split("\n");
for (int j = 0; j < lines.size(); j++) {
print_line(itos(line) + ": " + lines[j]);
line++;
}
ERR_PRINT(p_error);
}
ShaderGLES3::Version *ShaderGLES3::get_current_version() {
Version *_v = version_map.getptr(conditional_version);
if (_v) {
if (conditional_version.code_version != 0) {
CustomCode *cc = custom_code_map.getptr(conditional_version.code_version);
ERR_FAIL_COND_V(!cc, _v);
if (cc->version == _v->code_version)
return _v;
} else {
return _v;
}
}
if (!_v)
version_map[conditional_version] = Version();
Version &v = version_map[conditional_version];
if (!_v) {
v.uniform_location = memnew_arr(GLint, uniform_count);
} else {
if (v.ok) {
//bye bye shaders
glDeleteShader(v.vert_id);
glDeleteShader(v.frag_id);
glDeleteProgram(v.id);
v.id = 0;
}
}
v.ok = false;
/* SETUP CONDITIONALS */
Vector<const char *> strings;
#ifdef GLES_OVER_GL
strings.push_back("#version 330\n");
strings.push_back("#define GLES_OVER_GL\n");
#else
strings.push_back("#version 300 es\n");
#endif
for (int i = 0; i < custom_defines.size(); i++) {
strings.push_back(custom_defines[i].get_data());
}
for (int j = 0; j < conditional_count; j++) {
bool enable = ((1 << j) & conditional_version.version);
strings.push_back(enable ? conditional_defines[j] : "");
if (enable) {
DEBUG_PRINT(conditional_defines[j]);
}
}
//keep them around during the function
CharString code_string;
CharString code_string2;
CharString code_globals;
CharString material_string;
CustomCode *cc = NULL;
if (conditional_version.code_version > 0) {
//do custom code related stuff
ERR_FAIL_COND_V(!custom_code_map.has(conditional_version.code_version), NULL);
cc = &custom_code_map[conditional_version.code_version];
v.code_version = cc->version;
}
/* CREATE PROGRAM */
v.id = glCreateProgram();
ERR_FAIL_COND_V(v.id == 0, NULL);
/* VERTEX SHADER */
if (cc) {
for (int i = 0; i < cc->custom_defines.size(); i++) {
strings.push_back(cc->custom_defines[i].get_data());
DEBUG_PRINT("CD #" + itos(i) + ": " + String(cc->custom_defines[i]));
}
}
int strings_base_size = strings.size();
//vertex precision is high
strings.push_back("precision highp float;\n");
strings.push_back("precision highp int;\n");
#ifndef GLES_OVER_GL
strings.push_back("precision highp sampler2D;\n");
strings.push_back("precision highp samplerCube;\n");
strings.push_back("precision highp sampler2DArray;\n");
#endif
strings.push_back(vertex_code0.get_data());
if (cc) {
material_string = cc->uniforms.ascii();
strings.push_back(material_string.get_data());
}
strings.push_back(vertex_code1.get_data());
if (cc) {
code_globals = cc->vertex_globals.ascii();
strings.push_back(code_globals.get_data());
}
strings.push_back(vertex_code2.get_data());
if (cc) {
code_string = cc->vertex.ascii();
strings.push_back(code_string.get_data());
}
strings.push_back(vertex_code3.get_data());
#ifdef DEBUG_SHADER
DEBUG_PRINT("\nVertex Code:\n\n" + String(code_string.get_data()));
for (int i = 0; i < strings.size(); i++) {
//print_line("vert strings "+itos(i)+":"+String(strings[i]));
}
#endif
v.vert_id = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(v.vert_id, strings.size(), &strings[0], NULL);
glCompileShader(v.vert_id);
GLint status;
glGetShaderiv(v.vert_id, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
// error compiling
GLsizei iloglen;
glGetShaderiv(v.vert_id, GL_INFO_LOG_LENGTH, &iloglen);
if (iloglen < 0) {
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
v.id = 0;
ERR_PRINT("Vertex shader compilation failed with empty log");
} else {
if (iloglen == 0) {
iloglen = 4096; //buggy driver (Adreno 220+....)
}
char *ilogmem = (char *)memalloc(iloglen + 1);
ilogmem[iloglen] = 0;
glGetShaderInfoLog(v.vert_id, iloglen, &iloglen, ilogmem);
String err_string = get_shader_name() + ": Vertex Program Compilation Failed:\n";
err_string += ilogmem;
_display_error_with_code(err_string, strings);
memfree(ilogmem);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
v.id = 0;
}
ERR_FAIL_V(NULL);
}
//_display_error_with_code("pepo", strings);
/* FRAGMENT SHADER */
strings.resize(strings_base_size);
//fragment precision is medium
strings.push_back("precision highp float;\n");
strings.push_back("precision highp int;\n");
#ifndef GLES_OVER_GL
strings.push_back("precision highp sampler2D;\n");
strings.push_back("precision highp samplerCube;\n");
strings.push_back("precision highp sampler2DArray;\n");
#endif
strings.push_back(fragment_code0.get_data());
if (cc) {
material_string = cc->uniforms.ascii();
strings.push_back(material_string.get_data());
}
strings.push_back(fragment_code1.get_data());
if (cc) {
code_globals = cc->fragment_globals.ascii();
strings.push_back(code_globals.get_data());
}
strings.push_back(fragment_code2.get_data());
if (cc) {
code_string = cc->light.ascii();
strings.push_back(code_string.get_data());
}
strings.push_back(fragment_code3.get_data());
if (cc) {
code_string2 = cc->fragment.ascii();
strings.push_back(code_string2.get_data());
}
strings.push_back(fragment_code4.get_data());
#ifdef DEBUG_SHADER
DEBUG_PRINT("\nFragment Globals:\n\n" + String(code_globals.get_data()));
DEBUG_PRINT("\nFragment Code:\n\n" + String(code_string2.get_data()));
for (int i = 0; i < strings.size(); i++) {
//print_line("frag strings "+itos(i)+":"+String(strings[i]));
}
#endif
v.frag_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(v.frag_id, strings.size(), &strings[0], NULL);
glCompileShader(v.frag_id);
glGetShaderiv(v.frag_id, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
// error compiling
GLsizei iloglen;
glGetShaderiv(v.frag_id, GL_INFO_LOG_LENGTH, &iloglen);
if (iloglen < 0) {
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
v.id = 0;
ERR_PRINT("Fragment shader compilation failed with empty log");
} else {
if (iloglen == 0) {
iloglen = 4096; //buggy driver (Adreno 220+....)
}
char *ilogmem = (char *)memalloc(iloglen + 1);
ilogmem[iloglen] = 0;
glGetShaderInfoLog(v.frag_id, iloglen, &iloglen, ilogmem);
String err_string = get_shader_name() + ": Fragment Program Compilation Failed:\n";
err_string += ilogmem;
_display_error_with_code(err_string, strings);
ERR_PRINT(err_string.ascii().get_data());
memfree(ilogmem);
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
v.id = 0;
}
ERR_FAIL_V(NULL);
}
glAttachShader(v.id, v.frag_id);
glAttachShader(v.id, v.vert_id);
// bind attributes before linking
for (int i = 0; i < attribute_pair_count; i++) {
glBindAttribLocation(v.id, attribute_pairs[i].index, attribute_pairs[i].name);
}
//if feedback exists, set it up
if (feedback_count) {
Vector<const char *> feedback;
for (int i = 0; i < feedback_count; i++) {
if (feedbacks[i].conditional == -1 || (1 << feedbacks[i].conditional) & conditional_version.version) {
//conditional for this feedback is enabled
feedback.push_back(feedbacks[i].name);
}
}
if (feedback.size()) {
glTransformFeedbackVaryings(v.id, feedback.size(), feedback.ptr(), GL_INTERLEAVED_ATTRIBS);
}
}
glLinkProgram(v.id);
glGetProgramiv(v.id, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
// error linking
GLsizei iloglen;
glGetProgramiv(v.id, GL_INFO_LOG_LENGTH, &iloglen);
if (iloglen < 0) {
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
v.id = 0;
ERR_FAIL_COND_V(iloglen < 0, NULL);
}
if (iloglen == 0) {
iloglen = 4096; //buggy driver (Adreno 220+....)
}
char *ilogmem = (char *)Memory::alloc_static(iloglen + 1);
ilogmem[iloglen] = 0;
glGetProgramInfoLog(v.id, iloglen, &iloglen, ilogmem);
String err_string = get_shader_name() + ": Program LINK FAILED:\n";
err_string += ilogmem;
_display_error_with_code(err_string, strings);
ERR_PRINT(err_string.ascii().get_data());
Memory::free_static(ilogmem);
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
v.id = 0;
ERR_FAIL_V(NULL);
}
/* UNIFORMS */
glUseProgram(v.id);
//print_line("uniforms: ");
for (int j = 0; j < uniform_count; j++) {
v.uniform_location[j] = glGetUniformLocation(v.id, uniform_names[j]);
//print_line("uniform "+String(uniform_names[j])+" location "+itos(v.uniform_location[j]));
}
// set texture uniforms
for (int i = 0; i < texunit_pair_count; i++) {
GLint loc = glGetUniformLocation(v.id, texunit_pairs[i].name);
if (loc >= 0) {
if (texunit_pairs[i].index < 0) {
glUniform1i(loc, max_image_units + texunit_pairs[i].index); //negative, goes down
} else {
glUniform1i(loc, texunit_pairs[i].index);
}
}
}
// assign uniform block bind points
for (int i = 0; i < ubo_count; i++) {
GLint loc = glGetUniformBlockIndex(v.id, ubo_pairs[i].name);
if (loc >= 0)
glUniformBlockBinding(v.id, loc, ubo_pairs[i].index);
}
if (cc) {
v.texture_uniform_locations.resize(cc->texture_uniforms.size());
for (int i = 0; i < cc->texture_uniforms.size(); i++) {
v.texture_uniform_locations.write[i] = glGetUniformLocation(v.id, String(cc->texture_uniforms[i]).ascii().get_data());
glUniform1i(v.texture_uniform_locations[i], i + base_material_tex_index);
}
}
glUseProgram(0);
v.ok = true;
if (cc) {
cc->versions.insert(conditional_version.version);
}
return &v;
}
GLint ShaderGLES3::get_uniform_location(const String &p_name) const {
ERR_FAIL_COND_V(!version, -1);
return glGetUniformLocation(version->id, p_name.ascii().get_data());
}
void ShaderGLES3::setup(const char **p_conditional_defines, int p_conditional_count, const char **p_uniform_names, int p_uniform_count, const AttributePair *p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count, const Feedback *p_feedback, int p_feedback_count, const char *p_vertex_code, const char *p_fragment_code, int p_vertex_code_start, int p_fragment_code_start) {
ERR_FAIL_COND(version);
conditional_version.key = 0;
new_conditional_version.key = 0;
uniform_count = p_uniform_count;
conditional_count = p_conditional_count;
conditional_defines = p_conditional_defines;
uniform_names = p_uniform_names;
vertex_code = p_vertex_code;
fragment_code = p_fragment_code;
texunit_pairs = p_texunit_pairs;
texunit_pair_count = p_texunit_pair_count;
vertex_code_start = p_vertex_code_start;
fragment_code_start = p_fragment_code_start;
attribute_pairs = p_attribute_pairs;
attribute_pair_count = p_attribute_count;
ubo_pairs = p_ubo_pairs;
ubo_count = p_ubo_pair_count;
feedbacks = p_feedback;
feedback_count = p_feedback_count;
//split vertex and shader code (thank you, shader compiler programmers from you know what company).
{
String globals_tag = "\nVERTEX_SHADER_GLOBALS";
String material_tag = "\nMATERIAL_UNIFORMS";
String code_tag = "\nVERTEX_SHADER_CODE";
String code = vertex_code;
int cpos = code.find(material_tag);
if (cpos == -1) {
vertex_code0 = code.ascii();
} else {
vertex_code0 = code.substr(0, cpos).ascii();
code = code.substr(cpos + material_tag.length(), code.length());
cpos = code.find(globals_tag);
if (cpos == -1) {
vertex_code1 = code.ascii();
} else {
vertex_code1 = code.substr(0, cpos).ascii();
String code2 = code.substr(cpos + globals_tag.length(), code.length());
cpos = code2.find(code_tag);
if (cpos == -1) {
vertex_code2 = code2.ascii();
} else {
vertex_code2 = code2.substr(0, cpos).ascii();
vertex_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii();
}
}
}
}
{
String globals_tag = "\nFRAGMENT_SHADER_GLOBALS";
String material_tag = "\nMATERIAL_UNIFORMS";
String code_tag = "\nFRAGMENT_SHADER_CODE";
String light_code_tag = "\nLIGHT_SHADER_CODE";
String code = fragment_code;
int cpos = code.find(material_tag);
if (cpos == -1) {
fragment_code0 = code.ascii();
} else {
fragment_code0 = code.substr(0, cpos).ascii();
//print_line("CODE0:\n"+String(fragment_code0.get_data()));
code = code.substr(cpos + material_tag.length(), code.length());
cpos = code.find(globals_tag);
if (cpos == -1) {
fragment_code1 = code.ascii();
} else {
fragment_code1 = code.substr(0, cpos).ascii();
//print_line("CODE1:\n"+String(fragment_code1.get_data()));
String code2 = code.substr(cpos + globals_tag.length(), code.length());
cpos = code2.find(light_code_tag);
if (cpos == -1) {
fragment_code2 = code2.ascii();
} else {
fragment_code2 = code2.substr(0, cpos).ascii();
//print_line("CODE2:\n"+String(fragment_code2.get_data()));
String code3 = code2.substr(cpos + light_code_tag.length(), code2.length());
cpos = code3.find(code_tag);
if (cpos == -1) {
fragment_code3 = code3.ascii();
} else {
fragment_code3 = code3.substr(0, cpos).ascii();
//print_line("CODE3:\n"+String(fragment_code3.get_data()));
fragment_code4 = code3.substr(cpos + code_tag.length(), code3.length()).ascii();
//print_line("CODE4:\n"+String(fragment_code4.get_data()));
}
}
}
}
}
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_image_units);
}
void ShaderGLES3::finish() {
const VersionKey *V = NULL;
while ((V = version_map.next(V))) {
Version &v = version_map[*V];
glDeleteShader(v.vert_id);
glDeleteShader(v.frag_id);
glDeleteProgram(v.id);
memdelete_arr(v.uniform_location);
}
}
void ShaderGLES3::clear_caches() {
const VersionKey *V = NULL;
while ((V = version_map.next(V))) {
Version &v = version_map[*V];
glDeleteShader(v.vert_id);
glDeleteShader(v.frag_id);
glDeleteProgram(v.id);
memdelete_arr(v.uniform_location);
}
version_map.clear();
custom_code_map.clear();
version = NULL;
last_custom_code = 1;
uniforms_dirty = true;
}
uint32_t ShaderGLES3::create_custom_shader() {
custom_code_map[last_custom_code] = CustomCode();
custom_code_map[last_custom_code].version = 1;
return last_custom_code++;
}
void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String &p_vertex, const String &p_vertex_globals, const String &p_fragment, const String &p_light, const String &p_fragment_globals, const String &p_uniforms, const Vector<StringName> &p_texture_uniforms, const Vector<CharString> &p_custom_defines) {
ERR_FAIL_COND(!custom_code_map.has(p_code_id));
CustomCode *cc = &custom_code_map[p_code_id];
cc->vertex = p_vertex;
cc->vertex_globals = p_vertex_globals;
cc->fragment = p_fragment;
cc->fragment_globals = p_fragment_globals;
cc->light = p_light;
cc->texture_uniforms = p_texture_uniforms;
cc->uniforms = p_uniforms;
cc->custom_defines = p_custom_defines;
cc->version++;
}
void ShaderGLES3::set_custom_shader(uint32_t p_code_id) {
new_conditional_version.code_version = p_code_id;
}
void ShaderGLES3::free_custom_shader(uint32_t p_code_id) {
ERR_FAIL_COND(!custom_code_map.has(p_code_id));
if (conditional_version.code_version == p_code_id) {
conditional_version.code_version = 0; //do not keep using a version that is going away
unbind();
}
VersionKey key;
key.code_version = p_code_id;
for (Set<uint32_t>::Element *E = custom_code_map[p_code_id].versions.front(); E; E = E->next()) {
key.version = E->get();
ERR_CONTINUE(!version_map.has(key));
Version &v = version_map[key];
glDeleteShader(v.vert_id);
glDeleteShader(v.frag_id);
glDeleteProgram(v.id);
memdelete_arr(v.uniform_location);
v.id = 0;
version_map.erase(key);
}
custom_code_map.erase(p_code_id);
}
void ShaderGLES3::set_base_material_tex_index(int p_idx) {
base_material_tex_index = p_idx;
}
ShaderGLES3::ShaderGLES3() {
version = NULL;
last_custom_code = 1;
uniforms_dirty = true;
base_material_tex_index = 0;
}
ShaderGLES3::~ShaderGLES3() {
finish();
}

View file

@ -1,392 +0,0 @@
/*************************************************************************/
/* shader_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 SHADER_GLES3_H
#define SHADER_GLES3_H
#include "core/hash_map.h"
#include "core/map.h"
#include "core/math/camera_matrix.h"
#include "core/variant.h"
#include "platform_config.h"
#ifndef GLES3_INCLUDE_H
#include <GLES3/gl3.h>
#else
#include GLES3_INCLUDE_H
#endif
#include <stdio.h>
class ShaderGLES3 {
protected:
struct Enum {
uint64_t mask;
uint64_t shift;
const char *defines[16];
};
struct EnumValue {
uint64_t set_mask;
uint64_t clear_mask;
};
struct AttributePair {
const char *name;
int index;
};
struct UniformPair {
const char *name;
Variant::Type type_hint;
};
struct TexUnitPair {
const char *name;
int index;
};
struct UBOPair {
const char *name;
int index;
};
struct Feedback {
const char *name;
int conditional;
};
bool uniforms_dirty;
private:
//@TODO Optimize to a fixed set of shader pools and use a LRU
int uniform_count;
int texunit_pair_count;
int conditional_count;
int ubo_count;
int feedback_count;
int vertex_code_start;
int fragment_code_start;
int attribute_pair_count;
struct CustomCode {
String vertex;
String vertex_globals;
String fragment;
String fragment_globals;
String light;
String uniforms;
uint32_t version;
Vector<StringName> texture_uniforms;
Vector<CharString> custom_defines;
Set<uint32_t> versions;
};
struct Version {
GLuint id;
GLuint vert_id;
GLuint frag_id;
GLint *uniform_location;
Vector<GLint> texture_uniform_locations;
uint32_t code_version;
bool ok;
Version() :
id(0),
vert_id(0),
frag_id(0),
uniform_location(NULL),
code_version(0),
ok(false) {}
};
Version *version;
union VersionKey {
struct {
uint32_t version;
uint32_t code_version;
};
uint64_t key;
bool operator==(const VersionKey &p_key) const { return key == p_key.key; }
bool operator<(const VersionKey &p_key) const { return key < p_key.key; }
};
struct VersionKeyHash {
static _FORCE_INLINE_ uint32_t hash(const VersionKey &p_key) { return HashMapHasherDefault::hash(p_key.key); };
};
//this should use a way more cachefriendly version..
HashMap<VersionKey, Version, VersionKeyHash> version_map;
HashMap<uint32_t, CustomCode> custom_code_map;
uint32_t last_custom_code;
VersionKey conditional_version;
VersionKey new_conditional_version;
virtual String get_shader_name() const = 0;
const char **conditional_defines;
const char **uniform_names;
const AttributePair *attribute_pairs;
const TexUnitPair *texunit_pairs;
const UBOPair *ubo_pairs;
const Feedback *feedbacks;
const char *vertex_code;
const char *fragment_code;
CharString fragment_code0;
CharString fragment_code1;
CharString fragment_code2;
CharString fragment_code3;
CharString fragment_code4;
CharString vertex_code0;
CharString vertex_code1;
CharString vertex_code2;
CharString vertex_code3;
Vector<CharString> custom_defines;
int base_material_tex_index;
Version *get_current_version();
static ShaderGLES3 *active;
int max_image_units;
_FORCE_INLINE_ void _set_uniform_variant(GLint p_uniform, const Variant &p_value) {
if (p_uniform < 0)
return; // do none
switch (p_value.get_type()) {
case Variant::BOOL:
case Variant::INT: {
int val = p_value;
glUniform1i(p_uniform, val);
} break;
case Variant::REAL: {
real_t val = p_value;
glUniform1f(p_uniform, val);
} break;
case Variant::COLOR: {
Color val = p_value;
glUniform4f(p_uniform, val.r, val.g, val.b, val.a);
} break;
case Variant::VECTOR2: {
Vector2 val = p_value;
glUniform2f(p_uniform, val.x, val.y);
} break;
case Variant::VECTOR3: {
Vector3 val = p_value;
glUniform3f(p_uniform, val.x, val.y, val.z);
} break;
case Variant::PLANE: {
Plane val = p_value;
glUniform4f(p_uniform, val.normal.x, val.normal.y, val.normal.z, val.d);
} break;
case Variant::QUAT: {
Quat val = p_value;
glUniform4f(p_uniform, val.x, val.y, val.z, val.w);
} break;
case Variant::TRANSFORM2D: {
Transform2D tr = p_value;
GLfloat matrix[16] = { /* build a 16x16 matrix */
tr.elements[0][0],
tr.elements[0][1],
0,
0,
tr.elements[1][0],
tr.elements[1][1],
0,
0,
0,
0,
1,
0,
tr.elements[2][0],
tr.elements[2][1],
0,
1
};
glUniformMatrix4fv(p_uniform, 1, false, matrix);
} break;
case Variant::BASIS:
case Variant::TRANSFORM: {
Transform tr = p_value;
GLfloat matrix[16] = { /* build a 16x16 matrix */
tr.basis.elements[0][0],
tr.basis.elements[1][0],
tr.basis.elements[2][0],
0,
tr.basis.elements[0][1],
tr.basis.elements[1][1],
tr.basis.elements[2][1],
0,
tr.basis.elements[0][2],
tr.basis.elements[1][2],
tr.basis.elements[2][2],
0,
tr.origin.x,
tr.origin.y,
tr.origin.z,
1
};
glUniformMatrix4fv(p_uniform, 1, false, matrix);
} break;
default: {
ERR_FAIL();
} // do nothing
}
}
Map<uint32_t, Variant> uniform_defaults;
Map<uint32_t, CameraMatrix> uniform_cameras;
protected:
_FORCE_INLINE_ int _get_uniform(int p_which) const;
_FORCE_INLINE_ void _set_conditional(int p_which, bool p_value);
void setup(const char **p_conditional_defines, int p_conditional_count, const char **p_uniform_names, int p_uniform_count, const AttributePair *p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count, const Feedback *p_feedback, int p_feedback_count, const char *p_vertex_code, const char *p_fragment_code, int p_vertex_code_start, int p_fragment_code_start);
ShaderGLES3();
public:
enum {
CUSTOM_SHADER_DISABLED = 0
};
GLint get_uniform_location(const String &p_name) const;
GLint get_uniform_location(int p_index) const;
static _FORCE_INLINE_ ShaderGLES3 *get_active() { return active; };
bool bind();
void unbind();
void bind_uniforms();
inline GLuint get_program() const { return version ? version->id : 0; }
void clear_caches();
uint32_t create_custom_shader();
void set_custom_shader_code(uint32_t p_code_id, const String &p_vertex, const String &p_vertex_globals, const String &p_fragment, const String &p_light, const String &p_fragment_globals, const String &p_uniforms, const Vector<StringName> &p_texture_uniforms, const Vector<CharString> &p_custom_defines);
void set_custom_shader(uint32_t p_code_id);
void free_custom_shader(uint32_t p_code_id);
void set_uniform_default(int p_idx, const Variant &p_value) {
if (p_value.get_type() == Variant::NIL) {
uniform_defaults.erase(p_idx);
} else {
uniform_defaults[p_idx] = p_value;
}
uniforms_dirty = true;
}
uint32_t get_version() const { return new_conditional_version.version; }
_FORCE_INLINE_ bool is_version_valid() const { return version && version->ok; }
void set_uniform_camera(int p_idx, const CameraMatrix &p_mat) {
uniform_cameras[p_idx] = p_mat;
uniforms_dirty = true;
};
_FORCE_INLINE_ void set_texture_uniform(int p_idx, const Variant &p_value) {
ERR_FAIL_COND(!version);
ERR_FAIL_INDEX(p_idx, version->texture_uniform_locations.size());
_set_uniform_variant(version->texture_uniform_locations[p_idx], p_value);
}
_FORCE_INLINE_ GLint get_texture_uniform_location(int p_idx) {
ERR_FAIL_COND_V(!version, -1);
ERR_FAIL_INDEX_V(p_idx, version->texture_uniform_locations.size(), -1);
return version->texture_uniform_locations[p_idx];
}
virtual void init() = 0;
void finish();
void set_base_material_tex_index(int p_idx);
void add_custom_define(const String &p_define) {
custom_defines.push_back(p_define.utf8());
}
virtual ~ShaderGLES3();
};
// called a lot, made inline
int ShaderGLES3::_get_uniform(int p_which) const {
ERR_FAIL_INDEX_V(p_which, uniform_count, -1);
ERR_FAIL_COND_V(!version, -1);
return version->uniform_location[p_which];
}
void ShaderGLES3::_set_conditional(int p_which, bool p_value) {
ERR_FAIL_INDEX(p_which, conditional_count);
if (p_value)
new_conditional_version.version |= (1 << p_which);
else
new_conditional_version.version &= ~(1 << p_which);
}
#endif

View file

@ -1,23 +0,0 @@
#!/usr/bin/env python
Import('env')
if 'GLES3_GLSL' in env['BUILDERS']:
env.GLES3_GLSL('copy.glsl');
env.GLES3_GLSL('resolve.glsl');
env.GLES3_GLSL('canvas.glsl');
env.GLES3_GLSL('canvas_shadow.glsl');
env.GLES3_GLSL('scene.glsl');
env.GLES3_GLSL('cubemap_filter.glsl');
env.GLES3_GLSL('cube_to_dp.glsl');
env.GLES3_GLSL('blend_shape.glsl');
env.GLES3_GLSL('screen_space_reflection.glsl');
env.GLES3_GLSL('effect_blur.glsl');
env.GLES3_GLSL('subsurf_scattering.glsl');
env.GLES3_GLSL('ssao.glsl');
env.GLES3_GLSL('ssao_minify.glsl');
env.GLES3_GLSL('ssao_blur.glsl');
env.GLES3_GLSL('exposure.glsl');
env.GLES3_GLSL('tonemap.glsl');
env.GLES3_GLSL('particles.glsl');
env.GLES3_GLSL('lens_distorted.glsl');

View file

@ -1,194 +0,0 @@
/* clang-format off */
[vertex]
/*
from VisualServer:
ARRAY_VERTEX=0,
ARRAY_NORMAL=1,
ARRAY_TANGENT=2,
ARRAY_COLOR=3,
ARRAY_TEX_UV=4,
ARRAY_TEX_UV2=5,
ARRAY_BONES=6,
ARRAY_WEIGHTS=7,
ARRAY_INDEX=8,
*/
#ifdef USE_2D_VERTEX
#define VFORMAT vec2
#else
#define VFORMAT vec3
#endif
/* INPUT ATTRIBS */
layout(location = 0) in highp VFORMAT vertex_attrib;
/* clang-format on */
layout(location = 1) in vec3 normal_attrib;
#ifdef ENABLE_TANGENT
layout(location = 2) in vec4 tangent_attrib;
#endif
#ifdef ENABLE_COLOR
layout(location = 3) in vec4 color_attrib;
#endif
#ifdef ENABLE_UV
layout(location = 4) in vec2 uv_attrib;
#endif
#ifdef ENABLE_UV2
layout(location = 5) in vec2 uv2_attrib;
#endif
#ifdef ENABLE_SKELETON
layout(location = 6) in ivec4 bone_attrib;
layout(location = 7) in vec4 weight_attrib;
#endif
/* BLEND ATTRIBS */
#ifdef ENABLE_BLEND
layout(location = 8) in highp VFORMAT vertex_attrib_blend;
layout(location = 9) in vec3 normal_attrib_blend;
#ifdef ENABLE_TANGENT
layout(location = 10) in vec4 tangent_attrib_blend;
#endif
#ifdef ENABLE_COLOR
layout(location = 11) in vec4 color_attrib_blend;
#endif
#ifdef ENABLE_UV
layout(location = 12) in vec2 uv_attrib_blend;
#endif
#ifdef ENABLE_UV2
layout(location = 13) in vec2 uv2_attrib_blend;
#endif
#ifdef ENABLE_SKELETON
layout(location = 14) in ivec4 bone_attrib_blend;
layout(location = 15) in vec4 weight_attrib_blend;
#endif
#endif
/* OUTPUTS */
out VFORMAT vertex_out; //tfb:
#ifdef ENABLE_NORMAL
out vec3 normal_out; //tfb:ENABLE_NORMAL
#endif
#ifdef ENABLE_TANGENT
out vec4 tangent_out; //tfb:ENABLE_TANGENT
#endif
#ifdef ENABLE_COLOR
out vec4 color_out; //tfb:ENABLE_COLOR
#endif
#ifdef ENABLE_UV
out vec2 uv_out; //tfb:ENABLE_UV
#endif
#ifdef ENABLE_UV2
out vec2 uv2_out; //tfb:ENABLE_UV2
#endif
#ifdef ENABLE_SKELETON
out ivec4 bone_out; //tfb:ENABLE_SKELETON
out vec4 weight_out; //tfb:ENABLE_SKELETON
#endif
uniform float blend_amount;
void main() {
#ifdef ENABLE_BLEND
vertex_out = vertex_attrib_blend + vertex_attrib * blend_amount;
#ifdef ENABLE_NORMAL
normal_out = normal_attrib_blend + normal_attrib * blend_amount;
#endif
#ifdef ENABLE_TANGENT
tangent_out.xyz = tangent_attrib_blend.xyz + tangent_attrib.xyz * blend_amount;
tangent_out.w = tangent_attrib_blend.w; //just copy, no point in blending his
#endif
#ifdef ENABLE_COLOR
color_out = color_attrib_blend + color_attrib * blend_amount;
#endif
#ifdef ENABLE_UV
uv_out = uv_attrib_blend + uv_attrib * blend_amount;
#endif
#ifdef ENABLE_UV2
uv2_out = uv2_attrib_blend + uv2_attrib * blend_amount;
#endif
#ifdef ENABLE_SKELETON
bone_out = bone_attrib_blend;
weight_out = weight_attrib_blend + weight_attrib * blend_amount;
#endif
#else //ENABLE_BLEND
vertex_out = vertex_attrib * blend_amount;
#ifdef ENABLE_NORMAL
normal_out = normal_attrib * blend_amount;
#endif
#ifdef ENABLE_TANGENT
tangent_out.xyz = tangent_attrib.xyz * blend_amount;
tangent_out.w = tangent_attrib.w; //just copy, no point in blending his
#endif
#ifdef ENABLE_COLOR
color_out = color_attrib * blend_amount;
#endif
#ifdef ENABLE_UV
uv_out = uv_attrib * blend_amount;
#endif
#ifdef ENABLE_UV2
uv2_out = uv2_attrib * blend_amount;
#endif
#ifdef ENABLE_SKELETON
bone_out = bone_attrib;
weight_out = weight_attrib * blend_amount;
#endif
#endif
gl_Position = vec4(0.0);
}
/* clang-format off */
[fragment]
void main() {
}
/* clang-format on */

View file

@ -1,726 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec2 vertex;
/* clang-format on */
layout(location = 3) in vec4 color_attrib;
#ifdef USE_SKELETON
layout(location = 6) in uvec4 bone_indices; // attrib:6
layout(location = 7) in vec4 bone_weights; // attrib:7
#endif
#ifdef USE_TEXTURE_RECT
uniform vec4 dst_rect;
uniform vec4 src_rect;
#else
#ifdef USE_INSTANCING
layout(location = 8) in highp vec4 instance_xform0;
layout(location = 9) in highp vec4 instance_xform1;
layout(location = 10) in highp vec4 instance_xform2;
layout(location = 11) in lowp vec4 instance_color;
#ifdef USE_INSTANCE_CUSTOM
layout(location = 12) in highp vec4 instance_custom_data;
#endif
#endif
layout(location = 4) in highp vec2 uv_attrib;
// skeleton
#endif
uniform highp vec2 color_texpixel_size;
layout(std140) uniform CanvasItemData { //ubo:0
highp mat4 projection_matrix;
highp float time;
};
uniform highp mat4 modelview_matrix;
uniform highp mat4 extra_matrix;
out highp vec2 uv_interp;
out mediump vec4 color_interp;
#ifdef USE_NINEPATCH
out highp vec2 pixel_size_interp;
#endif
#ifdef USE_SKELETON
uniform mediump sampler2D skeleton_texture; // texunit:-4
uniform highp mat4 skeleton_transform;
uniform highp mat4 skeleton_transform_inverse;
#endif
#ifdef USE_LIGHTING
layout(std140) uniform LightData { //ubo:1
// light matrices
highp mat4 light_matrix;
highp mat4 light_local_matrix;
highp mat4 shadow_matrix;
highp vec4 light_color;
highp vec4 light_shadow_color;
highp vec2 light_pos;
highp float shadowpixel_size;
highp float shadow_gradient;
highp float light_height;
highp float light_outside_alpha;
highp float shadow_distance_mult;
};
out vec4 light_uv_interp;
out vec2 transformed_light_uv;
out vec4 local_rot;
#ifdef USE_SHADOWS
out highp vec2 pos;
#endif
const bool at_light_pass = true;
#else
const bool at_light_pass = false;
#endif
#if defined(USE_MATERIAL)
/* clang-format off */
layout(std140) uniform UniformData { //ubo:2
MATERIAL_UNIFORMS
};
/* clang-format on */
#endif
/* clang-format off */
VERTEX_SHADER_GLOBALS
/* clang-format on */
void main() {
vec4 color = color_attrib;
#ifdef USE_INSTANCING
mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0)));
color *= instance_color;
#ifdef USE_INSTANCE_CUSTOM
vec4 instance_custom = instance_custom_data;
#else
vec4 instance_custom = vec4(0.0);
#endif
#else
mat4 extra_matrix_instance = extra_matrix;
vec4 instance_custom = vec4(0.0);
#endif
#ifdef USE_TEXTURE_RECT
if (dst_rect.z < 0.0) { // Transpose is encoded as negative dst_rect.z
uv_interp = src_rect.xy + abs(src_rect.zw) * vertex.yx;
} else {
uv_interp = src_rect.xy + abs(src_rect.zw) * vertex;
}
highp vec4 outvec = vec4(dst_rect.xy + abs(dst_rect.zw) * mix(vertex, vec2(1.0, 1.0) - vertex, lessThan(src_rect.zw, vec2(0.0, 0.0))), 0.0, 1.0);
#else
uv_interp = uv_attrib;
highp vec4 outvec = vec4(vertex, 0.0, 1.0);
#endif
#ifdef USE_PARTICLES
//scale by texture size
outvec.xy /= color_texpixel_size;
#endif
#define extra_matrix extra_matrix_instance
float point_size = 1.0;
//for compatibility with the fragment shader we need to use uv here
vec2 uv = uv_interp;
{
/* clang-format off */
VERTEX_SHADER_CODE
/* clang-format on */
}
gl_PointSize = point_size;
uv_interp = uv;
#ifdef USE_NINEPATCH
pixel_size_interp = abs(dst_rect.zw) * vertex;
#endif
#if !defined(SKIP_TRANSFORM_USED)
outvec = extra_matrix * outvec;
outvec = modelview_matrix * outvec;
#endif
#undef extra_matrix
color_interp = color;
#ifdef USE_PIXEL_SNAP
outvec.xy = floor(outvec + 0.5).xy;
// precision issue on some hardware creates artifacts within texture
// offset uv by a small amount to avoid
uv_interp += 1e-5;
#endif
#ifdef USE_SKELETON
if (bone_weights != vec4(0.0)) { //must be a valid bone
//skeleton transform
ivec4 bone_indicesi = ivec4(bone_indices);
ivec2 tex_ofs = ivec2(bone_indicesi.x % 256, (bone_indicesi.x / 256) * 2);
highp mat2x4 m;
m = mat2x4(
texelFetch(skeleton_texture, tex_ofs, 0),
texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0)) *
bone_weights.x;
tex_ofs = ivec2(bone_indicesi.y % 256, (bone_indicesi.y / 256) * 2);
m += mat2x4(
texelFetch(skeleton_texture, tex_ofs, 0),
texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0)) *
bone_weights.y;
tex_ofs = ivec2(bone_indicesi.z % 256, (bone_indicesi.z / 256) * 2);
m += mat2x4(
texelFetch(skeleton_texture, tex_ofs, 0),
texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0)) *
bone_weights.z;
tex_ofs = ivec2(bone_indicesi.w % 256, (bone_indicesi.w / 256) * 2);
m += mat2x4(
texelFetch(skeleton_texture, tex_ofs, 0),
texelFetch(skeleton_texture, tex_ofs + ivec2(0, 1), 0)) *
bone_weights.w;
mat4 bone_matrix = skeleton_transform * transpose(mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))) * skeleton_transform_inverse;
outvec = bone_matrix * outvec;
}
#endif
gl_Position = projection_matrix * outvec;
#ifdef USE_LIGHTING
light_uv_interp.xy = (light_matrix * outvec).xy;
light_uv_interp.zw = (light_local_matrix * outvec).xy;
mat3 inverse_light_matrix = mat3(inverse(light_matrix));
inverse_light_matrix[0] = normalize(inverse_light_matrix[0]);
inverse_light_matrix[1] = normalize(inverse_light_matrix[1]);
inverse_light_matrix[2] = normalize(inverse_light_matrix[2]);
transformed_light_uv = (inverse_light_matrix * vec3(light_uv_interp.zw, 0.0)).xy; //for normal mapping
#ifdef USE_SHADOWS
pos = outvec.xy;
#endif
local_rot.xy = normalize((modelview_matrix * (extra_matrix_instance * vec4(1.0, 0.0, 0.0, 0.0))).xy);
local_rot.zw = normalize((modelview_matrix * (extra_matrix_instance * vec4(0.0, 1.0, 0.0, 0.0))).xy);
#ifdef USE_TEXTURE_RECT
local_rot.xy *= sign(src_rect.z);
local_rot.zw *= sign(src_rect.w);
#endif
#endif
}
/* clang-format off */
[fragment]
uniform mediump sampler2D color_texture; // texunit:0
/* clang-format on */
uniform highp vec2 color_texpixel_size;
uniform mediump sampler2D normal_texture; // texunit:1
in highp vec2 uv_interp;
in mediump vec4 color_interp;
#if defined(SCREEN_TEXTURE_USED)
uniform sampler2D screen_texture; // texunit:-3
#endif
#if defined(SCREEN_UV_USED)
uniform vec2 screen_pixel_size;
#endif
layout(std140) uniform CanvasItemData {
highp mat4 projection_matrix;
highp float time;
};
#ifdef USE_LIGHTING
layout(std140) uniform LightData {
highp mat4 light_matrix;
highp mat4 light_local_matrix;
highp mat4 shadow_matrix;
highp vec4 light_color;
highp vec4 light_shadow_color;
highp vec2 light_pos;
highp float shadowpixel_size;
highp float shadow_gradient;
highp float light_height;
highp float light_outside_alpha;
highp float shadow_distance_mult;
};
uniform lowp sampler2D light_texture; // texunit:-1
in vec4 light_uv_interp;
in vec2 transformed_light_uv;
in vec4 local_rot;
#ifdef USE_SHADOWS
uniform highp sampler2D shadow_texture; // texunit:-2
in highp vec2 pos;
#endif
const bool at_light_pass = true;
#else
const bool at_light_pass = false;
#endif
uniform mediump vec4 final_modulate;
layout(location = 0) out mediump vec4 frag_color;
#if defined(USE_MATERIAL)
/* clang-format off */
layout(std140) uniform UniformData {
MATERIAL_UNIFORMS
};
/* clang-format on */
#endif
/* clang-format off */
FRAGMENT_SHADER_GLOBALS
/* clang-format on */
void light_compute(
inout vec4 light,
inout vec2 light_vec,
inout float light_height,
inout vec4 light_color,
vec2 light_uv,
inout vec4 shadow_color,
inout vec2 shadow_vec,
vec3 normal,
vec2 uv,
#if defined(SCREEN_UV_USED)
vec2 screen_uv,
#endif
vec4 color) {
#if defined(USE_LIGHT_SHADER_CODE)
/* clang-format off */
LIGHT_SHADER_CODE
/* clang-format on */
#endif
}
#ifdef USE_TEXTURE_RECT
uniform vec4 dst_rect;
uniform vec4 src_rect;
uniform bool clip_rect_uv;
#ifdef USE_NINEPATCH
in highp vec2 pixel_size_interp;
uniform int np_repeat_v;
uniform int np_repeat_h;
uniform bool np_draw_center;
// left top right bottom in pixel coordinates
uniform vec4 np_margins;
float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, float s_ratio, int np_repeat, inout int draw_center) {
float tex_size = 1.0 / tex_pixel_size;
float screen_margin_begin = margin_begin / s_ratio;
float screen_margin_end = margin_end / s_ratio;
if (pixel < screen_margin_begin) {
return pixel * s_ratio * tex_pixel_size;
} else if (pixel >= draw_size - screen_margin_end) {
return (tex_size - (draw_size - pixel) * s_ratio) * tex_pixel_size;
} else {
if (!np_draw_center) {
draw_center--;
}
// np_repeat is passed as uniform using NinePatchRect::AxisStretchMode enum.
if (np_repeat == 0) { // Stretch.
// Convert to ratio.
float ratio = (pixel - screen_margin_begin) / (draw_size - screen_margin_begin - screen_margin_end);
// Scale to source texture.
return (margin_begin + ratio * (tex_size - margin_begin - margin_end)) * tex_pixel_size;
} else if (np_repeat == 1) { // Tile.
// Convert to offset.
float ofs = mod((pixel - screen_margin_begin), tex_size - margin_begin - margin_end);
// Scale to source texture.
return (margin_begin + ofs) * tex_pixel_size;
} else if (np_repeat == 2) { // Tile Fit.
// Calculate scale.
float src_area = draw_size - screen_margin_begin - screen_margin_end;
float dst_area = tex_size - margin_begin - margin_end;
float scale = max(1.0, floor(src_area / max(dst_area, 0.0000001) + 0.5));
// Convert to ratio.
float ratio = (pixel - screen_margin_begin) / src_area;
ratio = mod(ratio * scale, 1.0);
// Scale to source texture.
return (margin_begin + ratio * dst_area) * tex_pixel_size;
} else { // Shouldn't happen, but silences compiler warning.
return 0.0;
}
}
}
#endif
#endif
uniform bool use_default_normal;
void main() {
vec4 color = color_interp;
vec2 uv = uv_interp;
#ifdef USE_TEXTURE_RECT
#ifdef USE_NINEPATCH
int draw_center = 2;
float s_ratio = max((1.0 / color_texpixel_size.x) / abs(dst_rect.z), (1.0 / color_texpixel_size.y) / abs(dst_rect.w));
s_ratio = max(1.0, s_ratio);
uv = vec2(
map_ninepatch_axis(pixel_size_interp.x, abs(dst_rect.z), color_texpixel_size.x, np_margins.x, np_margins.z, s_ratio, np_repeat_h, draw_center),
map_ninepatch_axis(pixel_size_interp.y, abs(dst_rect.w), color_texpixel_size.y, np_margins.y, np_margins.w, s_ratio, np_repeat_v, draw_center));
if (draw_center == 0) {
color.a = 0.0;
}
uv = uv * src_rect.zw + src_rect.xy; //apply region if needed
#endif
if (clip_rect_uv) {
uv = clamp(uv, src_rect.xy, src_rect.xy + abs(src_rect.zw));
}
#endif
#if !defined(COLOR_USED)
//default behavior, texture by color
#ifdef USE_DISTANCE_FIELD
const float smoothing = 1.0 / 32.0;
float distance = textureLod(color_texture, uv, 0.0).a;
color.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance) * color.a;
#else
color *= texture(color_texture, uv);
#endif
#endif
vec3 normal;
#if defined(NORMAL_USED)
bool normal_used = true;
#else
bool normal_used = false;
#endif
if (use_default_normal) {
normal.xy = textureLod(normal_texture, uv, 0.0).xy * 2.0 - 1.0;
normal.z = sqrt(1.0 - dot(normal.xy, normal.xy));
normal_used = true;
} else {
normal = vec3(0.0, 0.0, 1.0);
}
#if defined(SCREEN_UV_USED)
vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size;
#endif
{
float normal_depth = 1.0;
#if defined(NORMALMAP_USED)
vec3 normal_map = vec3(0.0, 0.0, 1.0);
normal_used = true;
#endif
/* clang-format off */
FRAGMENT_SHADER_CODE
/* clang-format on */
#if defined(NORMALMAP_USED)
normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_depth);
#endif
}
#ifdef DEBUG_ENCODED_32
highp float enc32 = dot(color, highp vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0));
color = vec4(vec3(enc32), 1.0);
#endif
color *= final_modulate;
#ifdef USE_LIGHTING
vec2 light_vec = transformed_light_uv;
vec2 shadow_vec = transformed_light_uv;
if (normal_used) {
normal.xy = mat2(local_rot.xy, local_rot.zw) * normal.xy;
}
float att = 1.0;
vec2 light_uv = light_uv_interp.xy;
vec4 light = texture(light_texture, light_uv);
if (any(lessThan(light_uv_interp.xy, vec2(0.0, 0.0))) || any(greaterThanEqual(light_uv_interp.xy, vec2(1.0, 1.0)))) {
color.a *= light_outside_alpha; //invisible
} else {
float real_light_height = light_height;
vec4 real_light_color = light_color;
vec4 real_light_shadow_color = light_shadow_color;
#if defined(USE_LIGHT_SHADER_CODE)
//light is written by the light shader
light_compute(
light,
light_vec,
real_light_height,
real_light_color,
light_uv,
real_light_shadow_color,
shadow_vec,
normal,
uv,
#if defined(SCREEN_UV_USED)
screen_uv,
#endif
color);
#endif
light *= real_light_color;
if (normal_used) {
vec3 light_normal = normalize(vec3(light_vec, -real_light_height));
light *= max(dot(-light_normal, normal), 0.0);
}
color *= light;
#ifdef USE_SHADOWS
#ifdef SHADOW_VEC_USED
mat3 inverse_light_matrix = mat3(light_matrix);
inverse_light_matrix[0] = normalize(inverse_light_matrix[0]);
inverse_light_matrix[1] = normalize(inverse_light_matrix[1]);
inverse_light_matrix[2] = normalize(inverse_light_matrix[2]);
shadow_vec = (mat3(inverse_light_matrix) * vec3(shadow_vec, 0.0)).xy;
#else
shadow_vec = light_uv_interp.zw;
#endif
float angle_to_light = -atan(shadow_vec.x, shadow_vec.y);
float PI = 3.14159265358979323846264;
/*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays
float ang*/
float su, sz;
float abs_angle = abs(angle_to_light);
vec2 point;
float sh;
if (abs_angle < 45.0 * PI / 180.0) {
point = shadow_vec;
sh = 0.0 + (1.0 / 8.0);
} else if (abs_angle > 135.0 * PI / 180.0) {
point = -shadow_vec;
sh = 0.5 + (1.0 / 8.0);
} else if (angle_to_light > 0.0) {
point = vec2(shadow_vec.y, -shadow_vec.x);
sh = 0.25 + (1.0 / 8.0);
} else {
point = vec2(-shadow_vec.y, shadow_vec.x);
sh = 0.75 + (1.0 / 8.0);
}
highp vec4 s = shadow_matrix * vec4(point, 0.0, 1.0);
s.xyz /= s.w;
su = s.x * 0.5 + 0.5;
sz = s.z * 0.5 + 0.5;
//sz=lightlength(light_vec);
highp float shadow_attenuation = 0.0;
#ifdef USE_RGBA_SHADOWS
#define SHADOW_DEPTH(m_tex, m_uv) dot(texture((m_tex), (m_uv)), vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0))
#else
#define SHADOW_DEPTH(m_tex, m_uv) (texture((m_tex), (m_uv)).r)
#endif
#ifdef SHADOW_USE_GRADIENT
#define SHADOW_TEST(m_ofs) \
{ \
highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); \
shadow_attenuation += 1.0 - smoothstep(sd, sd + shadow_gradient, sz); \
}
#else
#define SHADOW_TEST(m_ofs) \
{ \
highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); \
shadow_attenuation += step(sz, sd); \
}
#endif
#ifdef SHADOW_FILTER_NEAREST
SHADOW_TEST(su);
#endif
#ifdef SHADOW_FILTER_PCF3
SHADOW_TEST(su + shadowpixel_size);
SHADOW_TEST(su);
SHADOW_TEST(su - shadowpixel_size);
shadow_attenuation /= 3.0;
#endif
#ifdef SHADOW_FILTER_PCF5
SHADOW_TEST(su + shadowpixel_size * 2.0);
SHADOW_TEST(su + shadowpixel_size);
SHADOW_TEST(su);
SHADOW_TEST(su - shadowpixel_size);
SHADOW_TEST(su - shadowpixel_size * 2.0);
shadow_attenuation /= 5.0;
#endif
#ifdef SHADOW_FILTER_PCF7
SHADOW_TEST(su + shadowpixel_size * 3.0);
SHADOW_TEST(su + shadowpixel_size * 2.0);
SHADOW_TEST(su + shadowpixel_size);
SHADOW_TEST(su);
SHADOW_TEST(su - shadowpixel_size);
SHADOW_TEST(su - shadowpixel_size * 2.0);
SHADOW_TEST(su - shadowpixel_size * 3.0);
shadow_attenuation /= 7.0;
#endif
#ifdef SHADOW_FILTER_PCF9
SHADOW_TEST(su + shadowpixel_size * 4.0);
SHADOW_TEST(su + shadowpixel_size * 3.0);
SHADOW_TEST(su + shadowpixel_size * 2.0);
SHADOW_TEST(su + shadowpixel_size);
SHADOW_TEST(su);
SHADOW_TEST(su - shadowpixel_size);
SHADOW_TEST(su - shadowpixel_size * 2.0);
SHADOW_TEST(su - shadowpixel_size * 3.0);
SHADOW_TEST(su - shadowpixel_size * 4.0);
shadow_attenuation /= 9.0;
#endif
#ifdef SHADOW_FILTER_PCF13
SHADOW_TEST(su + shadowpixel_size * 6.0);
SHADOW_TEST(su + shadowpixel_size * 5.0);
SHADOW_TEST(su + shadowpixel_size * 4.0);
SHADOW_TEST(su + shadowpixel_size * 3.0);
SHADOW_TEST(su + shadowpixel_size * 2.0);
SHADOW_TEST(su + shadowpixel_size);
SHADOW_TEST(su);
SHADOW_TEST(su - shadowpixel_size);
SHADOW_TEST(su - shadowpixel_size * 2.0);
SHADOW_TEST(su - shadowpixel_size * 3.0);
SHADOW_TEST(su - shadowpixel_size * 4.0);
SHADOW_TEST(su - shadowpixel_size * 5.0);
SHADOW_TEST(su - shadowpixel_size * 6.0);
shadow_attenuation /= 13.0;
#endif
//color *= shadow_attenuation;
color = mix(real_light_shadow_color, color, shadow_attenuation);
//use shadows
#endif
}
//use lighting
#endif
//color.rgb *= color.a;
frag_color = color;
}

View file

@ -1,45 +0,0 @@
/* clang-format off */
[vertex]
uniform highp mat4 projection_matrix;
/* clang-format on */
uniform highp mat4 light_matrix;
uniform highp mat4 world_matrix;
uniform highp float distance_norm;
layout(location = 0) in highp vec3 vertex;
out highp vec4 position_interp;
void main() {
gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex, 1.0)));
position_interp = gl_Position;
}
/* clang-format off */
[fragment]
in highp vec4 position_interp;
/* clang-format on */
#ifdef USE_RGBA_SHADOWS
layout(location = 0) out lowp vec4 distance_buf;
#else
layout(location = 0) out highp float distance_buf;
#endif
void main() {
highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; // bias
#ifdef USE_RGBA_SHADOWS
highp vec4 comp = fract(depth * vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0));
comp -= comp.xxyz * vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);
distance_buf = comp;
#else
distance_buf = depth;
#endif
}

View file

@ -1,270 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 vertex_attrib;
/* clang-format on */
#if defined(USE_CUBEMAP) || defined(USE_PANORAMA)
layout(location = 4) in vec3 cube_in;
#else
layout(location = 4) in vec2 uv_in;
#endif
layout(location = 5) in vec2 uv2_in;
#if defined(USE_CUBEMAP) || defined(USE_PANORAMA)
out vec3 cube_interp;
#else
out vec2 uv_interp;
#endif
out vec2 uv2_interp;
// These definitions are here because the shader-wrapper builder does
// not understand `#elif defined()`
#ifdef USE_DISPLAY_TRANSFORM
#endif
#ifdef USE_COPY_SECTION
uniform vec4 copy_section;
#elif defined(USE_DISPLAY_TRANSFORM)
uniform highp mat4 display_transform;
#endif
void main() {
#if defined(USE_CUBEMAP) || defined(USE_PANORAMA)
cube_interp = cube_in;
#elif defined(USE_ASYM_PANO)
uv_interp = vertex_attrib.xy;
#else
uv_interp = uv_in;
#ifdef V_FLIP
uv_interp.y = 1.0 - uv_interp.y;
#endif
#endif
uv2_interp = uv2_in;
gl_Position = vertex_attrib;
#ifdef USE_COPY_SECTION
uv_interp = copy_section.xy + uv_interp * copy_section.zw;
gl_Position.xy = (copy_section.xy + (gl_Position.xy * 0.5 + 0.5) * copy_section.zw) * 2.0 - 1.0;
#elif defined(USE_DISPLAY_TRANSFORM)
uv_interp = (display_transform * vec4(uv_in, 1.0, 1.0)).xy;
#endif
}
/* clang-format off */
[fragment]
#define M_PI 3.14159265359
#if !defined(USE_GLES_OVER_GL)
precision mediump float;
#endif
#if defined(USE_CUBEMAP) || defined(USE_PANORAMA)
in vec3 cube_interp;
#else
in vec2 uv_interp;
#endif
#ifdef USE_ASYM_PANO
uniform highp mat4 pano_transform;
uniform highp vec4 asym_proj;
#endif
// These definitions are here because the shader-wrapper builder does
// not understand `#elif defined()`
#ifdef USE_TEXTURE3D
#endif
#ifdef USE_TEXTURE2DARRAY
#endif
#ifdef YCBCR_TO_SRGB
#endif
#ifdef USE_CUBEMAP
uniform samplerCube source_cube; //texunit:0
#elif defined(USE_TEXTURE3D)
uniform sampler3D source_3d; //texunit:0
#elif defined(USE_TEXTURE2DARRAY)
uniform sampler2DArray source_2d_array; //texunit:0
#else
uniform sampler2D source; //texunit:0
#endif
#ifdef SEP_CBCR_TEXTURE
uniform sampler2D CbCr; //texunit:1
#endif
/* clang-format on */
#ifdef USE_LOD
uniform float mip_level;
#endif
#if defined(USE_TEXTURE3D) || defined(USE_TEXTURE2DARRAY)
uniform float layer;
#endif
#ifdef USE_MULTIPLIER
uniform float multiplier;
#endif
#if defined(USE_PANORAMA) || defined(USE_ASYM_PANO)
uniform highp mat4 sky_transform;
vec4 texturePanorama(vec3 normal, sampler2D pano) {
vec2 st = vec2(
atan(normal.x, normal.z),
acos(normal.y));
if (st.x < 0.0)
st.x += M_PI * 2.0;
st /= vec2(M_PI * 2.0, M_PI);
return textureLod(pano, st, 0.0);
}
#endif
uniform vec2 pixel_size;
in vec2 uv2_interp;
#ifdef USE_BCS
uniform vec3 bcs;
#endif
#ifdef USE_COLOR_CORRECTION
uniform sampler2D color_correction; //texunit:1
#endif
layout(location = 0) out vec4 frag_color;
void main() {
//vec4 color = color_interp;
#ifdef USE_PANORAMA
vec3 cube_normal = normalize(cube_interp);
cube_normal.z = -cube_normal.z;
cube_normal = mat3(sky_transform) * cube_normal;
cube_normal.z = -cube_normal.z;
vec4 color = texturePanorama(cube_normal, source);
#elif defined(USE_ASYM_PANO)
// When an asymmetrical projection matrix is used (applicable for stereoscopic rendering i.e. VR) we need to do this calculation per fragment to get a perspective correct result.
// Asymmetrical projection means the center of projection is no longer in the center of the screen but shifted.
// The Matrix[2][0] (= asym_proj.x) and Matrix[2][1] (= asym_proj.z) values are what provide the right shift in the image.
vec3 cube_normal;
cube_normal.z = -1.0;
cube_normal.x = (cube_normal.z * (-uv_interp.x - asym_proj.x)) / asym_proj.y;
cube_normal.y = (cube_normal.z * (-uv_interp.y - asym_proj.z)) / asym_proj.a;
cube_normal = mat3(sky_transform) * mat3(pano_transform) * cube_normal;
cube_normal.z = -cube_normal.z;
vec4 color = texturePanorama(normalize(cube_normal.xyz), source);
#elif defined(USE_CUBEMAP)
vec4 color = texture(source_cube, normalize(cube_interp));
#elif defined(USE_TEXTURE3D)
vec4 color = textureLod(source_3d, vec3(uv_interp, layer), 0.0);
#elif defined(USE_TEXTURE2DARRAY)
vec4 color = textureLod(source_2d_array, vec3(uv_interp, layer), 0.0);
#elif defined(SEP_CBCR_TEXTURE)
vec4 color;
color.r = textureLod(source, uv_interp, 0.0).r;
color.gb = textureLod(CbCr, uv_interp, 0.0).rg - vec2(0.5, 0.5);
color.a = 1.0;
#else
#ifdef USE_LOD
vec4 color = textureLod(source, uv_interp, mip_level);
#else
vec4 color = textureLod(source, uv_interp, 0.0);
#endif
#endif
#ifdef LINEAR_TO_SRGB
// regular Linear -> SRGB conversion
vec3 a = vec3(0.055);
color.rgb = mix((vec3(1.0) + a) * pow(color.rgb, vec3(1.0 / 2.4)) - a, 12.92 * color.rgb, lessThan(color.rgb, vec3(0.0031308)));
#elif defined(YCBCR_TO_SRGB)
// YCbCr -> SRGB conversion
// Using BT.709 which is the standard for HDTV
color.rgb = mat3(
vec3(1.00000, 1.00000, 1.00000),
vec3(0.00000, -0.18732, 1.85560),
vec3(1.57481, -0.46813, 0.00000)) *
color.rgb;
#endif
#ifdef SRGB_TO_LINEAR
color.rgb = mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), color.rgb * (1.0 / 12.92), lessThan(color.rgb, vec3(0.04045)));
#endif
#ifdef DEBUG_GRADIENT
color.rg = uv_interp;
color.b = 0.0;
#endif
#ifdef DISABLE_ALPHA
color.a = 1.0;
#endif
#ifdef GAUSSIAN_HORIZONTAL
color *= 0.38774;
color += texture(source, uv_interp + vec2(1.0, 0.0) * pixel_size) * 0.24477;
color += texture(source, uv_interp + vec2(2.0, 0.0) * pixel_size) * 0.06136;
color += texture(source, uv_interp + vec2(-1.0, 0.0) * pixel_size) * 0.24477;
color += texture(source, uv_interp + vec2(-2.0, 0.0) * pixel_size) * 0.06136;
#endif
#ifdef GAUSSIAN_VERTICAL
color *= 0.38774;
color += texture(source, uv_interp + vec2(0.0, 1.0) * pixel_size) * 0.24477;
color += texture(source, uv_interp + vec2(0.0, 2.0) * pixel_size) * 0.06136;
color += texture(source, uv_interp + vec2(0.0, -1.0) * pixel_size) * 0.24477;
color += texture(source, uv_interp + vec2(0.0, -2.0) * pixel_size) * 0.06136;
#endif
#ifdef USE_BCS
color.rgb = mix(vec3(0.0), color.rgb, bcs.x);
color.rgb = mix(vec3(0.5), color.rgb, bcs.y);
color.rgb = mix(vec3(dot(vec3(1.0), color.rgb) * 0.33333), color.rgb, bcs.z);
#endif
#ifdef USE_COLOR_CORRECTION
color.r = texture(color_correction, vec2(color.r, 0.0)).r;
color.g = texture(color_correction, vec2(color.g, 0.0)).g;
color.b = texture(color_correction, vec2(color.b, 0.0)).b;
#endif
#ifdef USE_MULTIPLIER
color.rgb *= multiplier;
#endif
frag_color = color;
}

View file

@ -1,79 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 vertex_attrib;
/* clang-format on */
layout(location = 4) in vec2 uv_in;
out vec2 uv_interp;
void main() {
uv_interp = uv_in;
gl_Position = vertex_attrib;
}
/* clang-format off */
[fragment]
uniform highp samplerCube source_cube; //texunit:0
/* clang-format on */
in vec2 uv_interp;
uniform bool z_flip;
uniform highp float z_far;
uniform highp float z_near;
uniform highp float bias;
void main() {
highp vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0);
/*
if (z_flip) {
normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
} else {
normal.z = -0.5 + 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
}
*/
//normal.z = sqrt(1.0 - dot(normal.xy, normal.xy));
//normal.xy *= 1.0 + normal.z;
normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
normal = normalize(normal);
/*
normal.z = 0.5;
normal = normalize(normal);
*/
if (!z_flip) {
normal.z = -normal.z;
}
//normal = normalize(vec3(uv_interp * 2.0 - 1.0, 1.0));
float depth = texture(source_cube, normal).r;
// absolute values for direction cosines, bigger value equals closer to basis axis
vec3 unorm = abs(normal);
if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
// x code
unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
} else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
// y code
unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
} else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
// z code
unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
} else {
// oh-no we messed up code
// has to be
unorm = vec3(1.0, 0.0, 0.0);
}
float depth_fix = 1.0 / dot(normal, unorm);
depth = 2.0 * depth - 1.0;
float linear_depth = 2.0 * z_near * z_far / (z_far + z_near - depth * (z_far - z_near));
gl_FragDepth = (linear_depth * depth_fix + bias) / z_far;
}

View file

@ -1,370 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec2 vertex;
/* clang-format on */
layout(location = 4) in highp vec2 uv;
out highp vec2 uv_interp;
void main() {
uv_interp = uv;
gl_Position = vec4(vertex, 0, 1);
}
/* clang-format off */
[fragment]
precision highp float;
/* clang-format on */
precision highp int;
#ifdef USE_SOURCE_PANORAMA
uniform sampler2D source_panorama; //texunit:0
uniform float source_resolution;
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
uniform sampler2DArray source_dual_paraboloid_array; //texunit:0
uniform int source_array_index;
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID
uniform sampler2D source_dual_paraboloid; //texunit:0
#endif
#if defined(USE_SOURCE_DUAL_PARABOLOID) || defined(COMPUTE_IRRADIANCE)
uniform float source_mip_level;
#endif
#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) && !defined(USE_SOURCE_DUAL_PARABOLOID)
uniform samplerCube source_cube; //texunit:0
#endif
uniform int face_id;
uniform float roughness;
in highp vec2 uv_interp;
layout(location = 0) out vec4 frag_color;
#define M_PI 3.14159265359
vec3 texelCoordToVec(vec2 uv, int faceID) {
mat3 faceUvVectors[6];
/*
// -x
faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
// +x
faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face
// -y
faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
// +y
faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z
faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face
// -z
faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
// +z
faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
*/
// -x
faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z
faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face
// +x
faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z
faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face
// -y
faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z
faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face
// +y
faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z
faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face
// -z
faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face
// +z
faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face
// out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
return normalize(result);
}
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
// Compute distribution direction
float Phi = 2.0 * M_PI * Xi.x;
float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));
float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
// Convert to spherical direction
vec3 H;
H.x = SinTheta * cos(Phi);
H.y = SinTheta * sin(Phi);
H.z = CosTheta;
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
vec3 TangentX = normalize(cross(UpVector, N));
vec3 TangentY = cross(N, TangentX);
// Tangent to world space
return TangentX * H.x + TangentY * H.y + N * H.z;
}
float DistributionGGX(vec3 N, vec3 H, float roughness) {
float a = roughness * roughness;
float a2 = a * a;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH * NdotH;
float nom = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = M_PI * denom * denom;
return nom / denom;
}
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
float GGX(float NdotV, float a) {
float k = a / 2.0;
return NdotV / (NdotV * (1.0 - k) + k);
}
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
float G_Smith(float a, float nDotV, float nDotL) {
return GGX(nDotL, a * a) * GGX(nDotV, a * a);
}
float radicalInverse_VdC(uint bits) {
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
}
vec2 Hammersley(uint i, uint N) {
return vec2(float(i) / float(N), radicalInverse_VdC(i));
}
#ifdef LOW_QUALITY
#define SAMPLE_COUNT 64u
#define SAMPLE_DELTA 0.1
#else
#define SAMPLE_COUNT 512u
#define SAMPLE_DELTA 0.03
#endif
uniform bool z_flip;
#ifdef USE_SOURCE_PANORAMA
vec4 texturePanorama(vec3 normal, sampler2D pano, float mipLevel) {
vec2 st = vec2(
atan(normal.x, normal.z),
acos(normal.y));
if (st.x < 0.0)
st.x += M_PI * 2.0;
st /= vec2(M_PI * 2.0, M_PI);
return textureLod(pano, st, mipLevel);
}
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
vec4 textureDualParaboloidArray(vec3 normal) {
vec3 norm = normalize(normal);
norm.xy /= 1.0 + abs(norm.z);
norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25);
if (norm.z < 0.0) {
norm.y = 0.5 - norm.y + 0.5;
}
return textureLod(source_dual_paraboloid_array, vec3(norm.xy, float(source_array_index)), 0.0);
}
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID
vec4 textureDualParaboloid(vec3 normal) {
vec3 norm = normalize(normal);
norm.xy /= 1.0 + abs(norm.z);
norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25);
if (norm.z < 0.0) {
norm.y = 0.5 - norm.y + 0.5;
}
return textureLod(source_dual_paraboloid, norm.xy, source_mip_level);
}
#endif
void main() {
#ifdef USE_DUAL_PARABOLOID
vec3 N = vec3(uv_interp * 2.0 - 1.0, 0.0);
N.z = 0.5 - 0.5 * ((N.x * N.x) + (N.y * N.y));
N = normalize(N);
if (z_flip) {
N.y = -N.y; //y is flipped to improve blending between both sides
N.z = -N.z;
}
#else
vec2 uv = (uv_interp * 2.0) - 1.0;
vec3 N = texelCoordToVec(uv, face_id);
#endif
//vec4 color = color_interp;
#ifdef USE_DIRECT_WRITE
#ifdef USE_SOURCE_PANORAMA
frag_color = vec4(texturePanorama(N, source_panorama, 0.0).rgb, 1.0);
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
frag_color = vec4(textureDualParaboloidArray(N).rgb, 1.0);
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID
frag_color = vec4(textureDualParaboloid(N).rgb, 1.0);
#endif
#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) && !defined(USE_SOURCE_DUAL_PARABOLOID)
N.y = -N.y;
frag_color = vec4(texture(N, source_cube).rgb, 1.0);
#endif
#else // USE_DIRECT_WRITE
#ifdef COMPUTE_IRRADIANCE
vec3 irradiance = vec3(0.0);
// tangent space calculation from origin point
vec3 UpVector = vec3(0.0, 1.0, 0.0);
vec3 TangentX = cross(UpVector, N);
vec3 TangentY = cross(N, TangentX);
float num_samples = 0.0f;
for (float phi = 0.0; phi < 2.0 * M_PI; phi += SAMPLE_DELTA) {
for (float theta = 0.0; theta < 0.5 * M_PI; theta += SAMPLE_DELTA) {
// Calculate sample positions
vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
// Find world vector of sample position
vec3 H = tangentSample.x * TangentX + tangentSample.y * TangentY + tangentSample.z * N;
vec2 st = vec2(atan(H.x, H.z), acos(H.y));
if (st.x < 0.0) {
st.x += M_PI * 2.0;
}
st /= vec2(M_PI * 2.0, M_PI);
irradiance += textureLod(source_panorama, st, source_mip_level).rgb * cos(theta) * sin(theta);
num_samples++;
}
}
irradiance = M_PI * irradiance * (1.0 / float(num_samples));
frag_color = vec4(irradiance, 1.0);
#else
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
for (uint sampleNum = 0u; sampleNum < SAMPLE_COUNT; sampleNum++) {
vec2 xi = Hammersley(sampleNum, SAMPLE_COUNT);
vec3 H = normalize(ImportanceSampleGGX(xi, roughness, N));
vec3 V = N;
vec3 L = normalize(2.0 * dot(V, H) * H - V);
float ndotl = max(dot(N, L), 0.0);
if (ndotl > 0.0) {
#ifdef USE_SOURCE_PANORAMA
float D = DistributionGGX(N, H, roughness);
float ndoth = max(dot(N, H), 0.0);
float hdotv = max(dot(H, V), 0.0);
float pdf = D * ndoth / (4.0 * hdotv) + 0.0001;
float saTexel = 4.0 * M_PI / (6.0 * source_resolution * source_resolution);
float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001);
float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
sum.rgb += texturePanorama(L, source_panorama, mipLevel).rgb * ndotl;
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY
sum.rgb += textureDualParaboloidArray(L).rgb * ndotl;
#endif
#ifdef USE_SOURCE_DUAL_PARABOLOID
sum.rgb += textureDualParaboloid(L).rgb * ndotl;
#endif
#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) && !defined(USE_SOURCE_DUAL_PARABOLOID)
L.y = -L.y;
sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl;
#endif
sum.a += ndotl;
}
}
sum /= sum.a;
frag_color = vec4(sum.rgb, 1.0);
#endif // COMPUTE_IRRADIANCE
#endif // USE_DIRECT_WRITE
}

View file

@ -1,293 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 vertex_attrib;
/* clang-format on */
layout(location = 4) in vec2 uv_in;
out vec2 uv_interp;
#ifdef USE_BLUR_SECTION
uniform vec4 blur_section;
#endif
void main() {
uv_interp = uv_in;
gl_Position = vertex_attrib;
#ifdef USE_BLUR_SECTION
uv_interp = blur_section.xy + uv_interp * blur_section.zw;
gl_Position.xy = (blur_section.xy + (gl_Position.xy * 0.5 + 0.5) * blur_section.zw) * 2.0 - 1.0;
#endif
}
/* clang-format off */
[fragment]
#if !defined(GLES_OVER_GL)
precision mediump float;
#endif
/* clang-format on */
in vec2 uv_interp;
uniform sampler2D source_color; //texunit:0
#ifdef SSAO_MERGE
uniform sampler2D source_ssao; //texunit:1
#endif
uniform float lod;
uniform vec2 pixel_size;
layout(location = 0) out vec4 frag_color;
#ifdef SSAO_MERGE
uniform vec4 ssao_color;
#endif
#if defined(GLOW_GAUSSIAN_HORIZONTAL) || defined(GLOW_GAUSSIAN_VERTICAL)
uniform float glow_strength;
#endif
#if defined(DOF_FAR_BLUR) || defined(DOF_NEAR_BLUR)
#ifdef DOF_QUALITY_LOW
const int dof_kernel_size = 5;
const int dof_kernel_from = 2;
const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388);
#endif
#ifdef DOF_QUALITY_MEDIUM
const int dof_kernel_size = 11;
const int dof_kernel_from = 5;
const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037);
#endif
#ifdef DOF_QUALITY_HIGH
const int dof_kernel_size = 21;
const int dof_kernel_from = 10;
const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174);
#endif
uniform sampler2D dof_source_depth; //texunit:1
uniform float dof_begin;
uniform float dof_end;
uniform vec2 dof_dir;
uniform float dof_radius;
#ifdef DOF_NEAR_BLUR_MERGE
uniform sampler2D source_dof_original; //texunit:2
#endif
#endif
#ifdef GLOW_FIRST_PASS
uniform float exposure;
uniform float white;
uniform highp float luminance_cap;
#ifdef GLOW_USE_AUTO_EXPOSURE
uniform highp sampler2D source_auto_exposure; //texunit:1
uniform highp float auto_exposure_grey;
#endif
uniform float glow_bloom;
uniform float glow_hdr_threshold;
uniform float glow_hdr_scale;
#endif
uniform float camera_z_far;
uniform float camera_z_near;
void main() {
#ifdef GAUSSIAN_HORIZONTAL
vec2 pix_size = pixel_size;
pix_size *= 0.5; //reading from larger buffer, so use more samples
// sigma 2
vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pix_size, lod) * 0.214607;
color += textureLod(source_color, uv_interp + vec2(1.0, 0.0) * pix_size, lod) * 0.189879;
color += textureLod(source_color, uv_interp + vec2(2.0, 0.0) * pix_size, lod) * 0.131514;
color += textureLod(source_color, uv_interp + vec2(3.0, 0.0) * pix_size, lod) * 0.071303;
color += textureLod(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size, lod) * 0.189879;
color += textureLod(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size, lod) * 0.131514;
color += textureLod(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size, lod) * 0.071303;
frag_color = color;
#endif
#ifdef GAUSSIAN_VERTICAL
vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pixel_size, lod) * 0.38774;
color += textureLod(source_color, uv_interp + vec2(0.0, 1.0) * pixel_size, lod) * 0.24477;
color += textureLod(source_color, uv_interp + vec2(0.0, 2.0) * pixel_size, lod) * 0.06136;
color += textureLod(source_color, uv_interp + vec2(0.0, -1.0) * pixel_size, lod) * 0.24477;
color += textureLod(source_color, uv_interp + vec2(0.0, -2.0) * pixel_size, lod) * 0.06136;
frag_color = color;
#endif
//glow uses larger sigma for a more rounded blur effect
#ifdef GLOW_GAUSSIAN_HORIZONTAL
vec2 pix_size = pixel_size;
pix_size *= 0.5; //reading from larger buffer, so use more samples
vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pix_size, lod) * 0.174938;
color += textureLod(source_color, uv_interp + vec2(1.0, 0.0) * pix_size, lod) * 0.165569;
color += textureLod(source_color, uv_interp + vec2(2.0, 0.0) * pix_size, lod) * 0.140367;
color += textureLod(source_color, uv_interp + vec2(3.0, 0.0) * pix_size, lod) * 0.106595;
color += textureLod(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size, lod) * 0.165569;
color += textureLod(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size, lod) * 0.140367;
color += textureLod(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size, lod) * 0.106595;
color *= glow_strength;
frag_color = color;
#endif
#ifdef GLOW_GAUSSIAN_VERTICAL
vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pixel_size, lod) * 0.288713;
color += textureLod(source_color, uv_interp + vec2(0.0, 1.0) * pixel_size, lod) * 0.233062;
color += textureLod(source_color, uv_interp + vec2(0.0, 2.0) * pixel_size, lod) * 0.122581;
color += textureLod(source_color, uv_interp + vec2(0.0, -1.0) * pixel_size, lod) * 0.233062;
color += textureLod(source_color, uv_interp + vec2(0.0, -2.0) * pixel_size, lod) * 0.122581;
color *= glow_strength;
frag_color = color;
#endif
#ifdef DOF_FAR_BLUR
vec4 color_accum = vec4(0.0);
float depth = textureLod(dof_source_depth, uv_interp, 0.0).r;
depth = depth * 2.0 - 1.0;
#ifdef USE_ORTHOGONAL_PROJECTION
depth = ((depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
#else
depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
#endif
float amount = smoothstep(dof_begin, dof_end, depth);
float k_accum = 0.0;
for (int i = 0; i < dof_kernel_size; i++) {
int int_ofs = i - dof_kernel_from;
vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * amount * dof_radius;
float tap_k = dof_kernel[i];
float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
tap_depth = tap_depth * 2.0 - 1.0;
#ifdef USE_ORTHOGONAL_PROJECTION
tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
#else
tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
#endif
float tap_amount = mix(smoothstep(dof_begin, dof_end, tap_depth), 1.0, int_ofs == 0);
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
vec4 tap_color = textureLod(source_color, tap_uv, 0.0) * tap_k;
k_accum += tap_k * tap_amount;
color_accum += tap_color * tap_amount;
}
if (k_accum > 0.0) {
color_accum /= k_accum;
}
frag_color = color_accum; ///k_accum;
#endif
#ifdef DOF_NEAR_BLUR
vec4 color_accum = vec4(0.0);
float max_accum = 0.0;
for (int i = 0; i < dof_kernel_size; i++) {
int int_ofs = i - dof_kernel_from;
vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * dof_radius;
float ofs_influence = max(0.0, 1.0 - float(abs(int_ofs)) / float(dof_kernel_from));
float tap_k = dof_kernel[i];
vec4 tap_color = textureLod(source_color, tap_uv, 0.0);
float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
tap_depth = tap_depth * 2.0 - 1.0;
#ifdef USE_ORTHOGONAL_PROJECTION
tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
#else
tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
#endif
float tap_amount = 1.0 - smoothstep(dof_end, dof_begin, tap_depth);
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
#ifdef DOF_NEAR_FIRST_TAP
tap_color.a = 1.0 - smoothstep(dof_end, dof_begin, tap_depth);
#endif
max_accum = max(max_accum, tap_amount * ofs_influence);
color_accum += tap_color * tap_k;
}
color_accum.a = max(color_accum.a, sqrt(max_accum));
#ifdef DOF_NEAR_BLUR_MERGE
vec4 original = textureLod(source_dof_original, uv_interp, 0.0);
color_accum = mix(original, color_accum, color_accum.a);
#endif
#ifndef DOF_NEAR_FIRST_TAP
//color_accum=vec4(vec3(color_accum.a),1.0);
#endif
frag_color = color_accum;
#endif
#ifdef GLOW_FIRST_PASS
#ifdef GLOW_USE_AUTO_EXPOSURE
frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / auto_exposure_grey;
#endif
frag_color *= exposure;
float luminance = max(frag_color.r, max(frag_color.g, frag_color.b));
float feedback = max(smoothstep(glow_hdr_threshold, glow_hdr_threshold + glow_hdr_scale, luminance), glow_bloom);
frag_color = min(frag_color * feedback, vec4(luminance_cap));
#endif
#ifdef SIMPLE_COPY
vec4 color = textureLod(source_color, uv_interp, 0.0);
frag_color = color;
#endif
#ifdef SSAO_MERGE
vec4 color = textureLod(source_color, uv_interp, 0.0);
float ssao = textureLod(source_ssao, uv_interp, 0.0).r;
frag_color = vec4(mix(color.rgb, color.rgb * mix(ssao_color.rgb, vec3(1.0), ssao), color.a), 1.0);
#endif
}

View file

@ -1,88 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 vertex_attrib;
/* clang-format on */
void main() {
gl_Position = vertex_attrib;
}
/* clang-format off */
[fragment]
uniform highp sampler2D source_exposure; //texunit:0
/* clang-format on */
#ifdef EXPOSURE_BEGIN
uniform highp ivec2 source_render_size;
uniform highp ivec2 target_size;
#endif
#ifdef EXPOSURE_END
uniform highp sampler2D prev_exposure; //texunit:1
uniform highp float exposure_adjust;
uniform highp float min_luminance;
uniform highp float max_luminance;
#endif
layout(location = 0) out highp float exposure;
void main() {
#ifdef EXPOSURE_BEGIN
ivec2 src_pos = ivec2(gl_FragCoord.xy) * source_render_size / target_size;
#if 1
//more precise and expensive, but less jittery
ivec2 next_pos = ivec2(gl_FragCoord.xy + ivec2(1)) * source_render_size / target_size;
next_pos = max(next_pos, src_pos + ivec2(1)); //so it at least reads one pixel
highp vec3 source_color = vec3(0.0);
for (int i = src_pos.x; i < next_pos.x; i++) {
for (int j = src_pos.y; j < next_pos.y; j++) {
source_color += texelFetch(source_exposure, ivec2(i, j), 0).rgb;
}
}
source_color /= float((next_pos.x - src_pos.x) * (next_pos.y - src_pos.y));
#else
highp vec3 source_color = texelFetch(source_exposure, src_pos, 0).rgb;
#endif
exposure = max(source_color.r, max(source_color.g, source_color.b));
#else
ivec2 coord = ivec2(gl_FragCoord.xy);
exposure = texelFetch(source_exposure, coord * 3 + ivec2(0, 0), 0).r;
exposure += texelFetch(source_exposure, coord * 3 + ivec2(1, 0), 0).r;
exposure += texelFetch(source_exposure, coord * 3 + ivec2(2, 0), 0).r;
exposure += texelFetch(source_exposure, coord * 3 + ivec2(0, 1), 0).r;
exposure += texelFetch(source_exposure, coord * 3 + ivec2(1, 1), 0).r;
exposure += texelFetch(source_exposure, coord * 3 + ivec2(2, 1), 0).r;
exposure += texelFetch(source_exposure, coord * 3 + ivec2(0, 2), 0).r;
exposure += texelFetch(source_exposure, coord * 3 + ivec2(1, 2), 0).r;
exposure += texelFetch(source_exposure, coord * 3 + ivec2(2, 2), 0).r;
exposure *= (1.0 / 9.0);
#ifdef EXPOSURE_END
#ifdef EXPOSURE_FORCE_SET
//will stay as is
#else
highp float prev_lum = texelFetch(prev_exposure, ivec2(0, 0), 0).r; //1 pixel previous exposure
exposure = clamp(prev_lum + (exposure - prev_lum) * exposure_adjust, min_luminance, max_luminance);
#endif //EXPOSURE_FORCE_SET
#endif //EXPOSURE_END
#endif //EXPOSURE_BEGIN
}

View file

@ -1,64 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 vertex_attrib;
/* clang-format on */
uniform vec2 offset;
uniform vec2 scale;
out vec2 uv_interp;
void main() {
uv_interp = vertex_attrib.xy * 2.0 - 1.0;
vec2 v = vertex_attrib.xy * scale + offset;
gl_Position = vec4(v, 0.0, 1.0);
}
/* clang-format off */
[fragment]
uniform sampler2D source; //texunit:0
/* clang-format on */
uniform vec2 eye_center;
uniform float k1;
uniform float k2;
uniform float upscale;
uniform float aspect_ratio;
in vec2 uv_interp;
layout(location = 0) out vec4 frag_color;
void main() {
vec2 coords = uv_interp;
vec2 offset = coords - eye_center;
// take aspect ratio into account
offset.y /= aspect_ratio;
// distort
vec2 offset_sq = offset * offset;
float radius_sq = offset_sq.x + offset_sq.y;
float radius_s4 = radius_sq * radius_sq;
float distortion_scale = 1.0 + (k1 * radius_sq) + (k2 * radius_s4);
offset *= distortion_scale;
// reapply aspect ratio
offset.y *= aspect_ratio;
// add our eye center back in
coords = offset + eye_center;
coords /= upscale;
// and check our color
if (coords.x < -1.0 || coords.y < -1.0 || coords.x > 1.0 || coords.y > 1.0) {
frag_color = vec4(0.0, 0.0, 0.0, 1.0);
} else {
coords = (coords + vec2(1.0)) / vec2(2.0);
frag_color = textureLod(source, coords, 0.0);
}
}

View file

@ -1,267 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 color;
/* clang-format on */
layout(location = 1) in highp vec4 velocity_active;
layout(location = 2) in highp vec4 custom;
layout(location = 3) in highp vec4 xform_1;
layout(location = 4) in highp vec4 xform_2;
layout(location = 5) in highp vec4 xform_3;
struct Attractor {
vec3 pos;
vec3 dir;
float radius;
float eat_radius;
float strength;
float attenuation;
};
#define MAX_ATTRACTORS 64
uniform bool emitting;
uniform float system_phase;
uniform float prev_system_phase;
uniform int total_particles;
uniform float explosiveness;
uniform float randomness;
uniform float time;
uniform float delta;
uniform int attractor_count;
uniform Attractor attractors[MAX_ATTRACTORS];
uniform bool clear;
uniform uint cycle;
uniform float lifetime;
uniform mat4 emission_transform;
uniform uint random_seed;
out highp vec4 out_color; //tfb:
out highp vec4 out_velocity_active; //tfb:
out highp vec4 out_custom; //tfb:
out highp vec4 out_xform_1; //tfb:
out highp vec4 out_xform_2; //tfb:
out highp vec4 out_xform_3; //tfb:
#if defined(USE_MATERIAL)
/* clang-format off */
layout(std140) uniform UniformData { //ubo:0
MATERIAL_UNIFORMS
};
/* clang-format on */
#endif
/* clang-format off */
VERTEX_SHADER_GLOBALS
/* clang-format on */
uint hash(uint x) {
x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b);
x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b);
x = (x >> uint(16)) ^ x;
return x;
}
void main() {
#ifdef PARTICLES_COPY
out_color = color;
out_velocity_active = velocity_active;
out_custom = custom;
out_xform_1 = xform_1;
out_xform_2 = xform_2;
out_xform_3 = xform_3;
#else
bool apply_forces = true;
bool apply_velocity = true;
float local_delta = delta;
float mass = 1.0;
float restart_phase = float(gl_VertexID) / float(total_particles);
if (randomness > 0.0) {
uint seed = cycle;
if (restart_phase >= system_phase) {
seed -= uint(1);
}
seed *= uint(total_particles);
seed += uint(gl_VertexID);
float random = float(hash(seed) % uint(65536)) / 65536.0;
restart_phase += randomness * random * 1.0 / float(total_particles);
}
restart_phase *= (1.0 - explosiveness);
bool restart = false;
bool shader_active = velocity_active.a > 0.5;
if (system_phase > prev_system_phase) {
// restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed
if (restart_phase >= prev_system_phase && restart_phase < system_phase) {
restart = true;
#ifdef USE_FRACTIONAL_DELTA
local_delta = (system_phase - restart_phase) * lifetime;
#endif
}
} else if (delta > 0.0) {
if (restart_phase >= prev_system_phase) {
restart = true;
#ifdef USE_FRACTIONAL_DELTA
local_delta = (1.0 - restart_phase + system_phase) * lifetime;
#endif
} else if (restart_phase < system_phase) {
restart = true;
#ifdef USE_FRACTIONAL_DELTA
local_delta = (system_phase - restart_phase) * lifetime;
#endif
}
}
uint current_cycle = cycle;
if (system_phase < restart_phase) {
current_cycle -= uint(1);
}
uint particle_number = current_cycle * uint(total_particles) + uint(gl_VertexID);
int index = int(gl_VertexID);
if (restart) {
shader_active = emitting;
}
mat4 xform;
#if defined(ENABLE_KEEP_DATA)
if (clear) {
#else
if (clear || restart) {
#endif
out_color = vec4(1.0);
out_velocity_active = vec4(0.0);
out_custom = vec4(0.0);
if (!restart)
shader_active = false;
xform = mat4(
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, 1.0, 0.0, 0.0),
vec4(0.0, 0.0, 1.0, 0.0),
vec4(0.0, 0.0, 0.0, 1.0));
} else {
out_color = color;
out_velocity_active = velocity_active;
out_custom = custom;
xform = transpose(mat4(xform_1, xform_2, xform_3, vec4(vec3(0.0), 1.0)));
}
if (shader_active) {
//execute shader
{
/* clang-format off */
VERTEX_SHADER_CODE
/* clang-format on */
}
#if !defined(DISABLE_FORCE)
if (false) {
vec3 force = vec3(0.0);
for (int i = 0; i < attractor_count; i++) {
vec3 rel_vec = xform[3].xyz - attractors[i].pos;
float dist = length(rel_vec);
if (attractors[i].radius < dist)
continue;
if (attractors[i].eat_radius > 0.0 && attractors[i].eat_radius > dist) {
out_velocity_active.a = 0.0;
}
rel_vec = normalize(rel_vec);
float attenuation = pow(dist / attractors[i].radius, attractors[i].attenuation);
if (attractors[i].dir == vec3(0.0)) {
//towards center
force += attractors[i].strength * rel_vec * attenuation * mass;
} else {
force += attractors[i].strength * attractors[i].dir * attenuation * mass;
}
}
out_velocity_active.xyz += force * local_delta;
}
#endif
#if !defined(DISABLE_VELOCITY)
if (true) {
xform[3].xyz += out_velocity_active.xyz * local_delta;
}
#endif
} else {
xform = mat4(0.0);
}
xform = transpose(xform);
out_velocity_active.a = mix(0.0, 1.0, shader_active);
out_xform_1 = xform[0];
out_xform_2 = xform[1];
out_xform_3 = xform[2];
#endif //PARTICLES_COPY
}
/* clang-format off */
[fragment]
// any code here is never executed, stuff is filled just so it works
#if defined(USE_MATERIAL)
layout(std140) uniform UniformData {
MATERIAL_UNIFORMS
};
#endif
FRAGMENT_SHADER_GLOBALS
void main() {
{
LIGHT_SHADER_CODE
}
{
FRAGMENT_SHADER_CODE
}
}
/* clang-format on */

View file

@ -1,44 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 vertex_attrib;
/* clang-format on */
layout(location = 4) in vec2 uv_in;
out vec2 uv_interp;
void main() {
uv_interp = uv_in;
gl_Position = vertex_attrib;
}
/* clang-format off */
[fragment]
#if !defined(GLES_OVER_GL)
precision mediump float;
#endif
/* clang-format on */
in vec2 uv_interp;
uniform sampler2D source_specular; // texunit:0
uniform sampler2D source_ssr; // texunit:1
uniform vec2 pixel_size;
in vec2 uv2_interp;
layout(location = 0) out vec4 frag_color;
void main() {
vec4 specular = texture(source_specular, uv_interp);
#ifdef USE_SSR
vec4 ssr = textureLod(source_ssr, uv_interp, 0.0);
specular.rgb = mix(specular.rgb, ssr.rgb * specular.a, ssr.a);
#endif
frag_color = vec4(specular.rgb, 1.0);
}

File diff suppressed because it is too large Load diff

View file

@ -1,286 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 vertex_attrib;
/* clang-format on */
layout(location = 4) in vec2 uv_in;
out vec2 uv_interp;
out vec2 pos_interp;
void main() {
uv_interp = uv_in;
gl_Position = vertex_attrib;
pos_interp.xy = gl_Position.xy;
}
/* clang-format off */
[fragment]
in vec2 uv_interp;
/* clang-format on */
in vec2 pos_interp;
uniform sampler2D source_diffuse; //texunit:0
uniform sampler2D source_normal_roughness; //texunit:1
uniform sampler2D source_depth; //texunit:2
uniform float camera_z_near;
uniform float camera_z_far;
uniform vec2 viewport_size;
uniform vec2 pixel_size;
uniform float filter_mipmap_levels;
uniform mat4 inverse_projection;
uniform mat4 projection;
uniform int num_steps;
uniform float depth_tolerance;
uniform float distance_fade;
uniform float curve_fade_in;
layout(location = 0) out vec4 frag_color;
vec2 view_to_screen(vec3 view_pos, out float w) {
vec4 projected = projection * vec4(view_pos, 1.0);
projected.xyz /= projected.w;
projected.xy = projected.xy * 0.5 + 0.5;
w = projected.w;
return projected.xy;
}
#define M_PI 3.14159265359
void main() {
vec4 diffuse = texture(source_diffuse, uv_interp);
vec4 normal_roughness = texture(source_normal_roughness, uv_interp);
vec3 normal;
normal = normal_roughness.xyz * 2.0 - 1.0;
float roughness = normal_roughness.w;
float depth_tex = texture(source_depth, uv_interp).r;
vec4 world_pos = inverse_projection * vec4(uv_interp * 2.0 - 1.0, depth_tex * 2.0 - 1.0, 1.0);
vec3 vertex = world_pos.xyz / world_pos.w;
vec3 view_dir = normalize(vertex);
vec3 ray_dir = normalize(reflect(view_dir, normal));
if (dot(ray_dir, normal) < 0.001) {
frag_color = vec4(0.0);
return;
}
//ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0);
//ray_dir = normalize(vec3(1.0, 1.0, -1.0));
////////////////
// make ray length and clip it against the near plane (don't want to trace beyond visible)
float ray_len = (vertex.z + ray_dir.z * camera_z_far) > -camera_z_near ? (-camera_z_near - vertex.z) / ray_dir.z : camera_z_far;
vec3 ray_end = vertex + ray_dir * ray_len;
float w_begin;
vec2 vp_line_begin = view_to_screen(vertex, w_begin);
float w_end;
vec2 vp_line_end = view_to_screen(ray_end, w_end);
vec2 vp_line_dir = vp_line_end - vp_line_begin;
// we need to interpolate w along the ray, to generate perspective correct reflections
w_begin = 1.0 / w_begin;
w_end = 1.0 / w_end;
float z_begin = vertex.z * w_begin;
float z_end = ray_end.z * w_end;
vec2 line_begin = vp_line_begin / pixel_size;
vec2 line_dir = vp_line_dir / pixel_size;
float z_dir = z_end - z_begin;
float w_dir = w_end - w_begin;
// clip the line to the viewport edges
float scale_max_x = min(1.0, 0.99 * (1.0 - vp_line_begin.x) / max(1e-5, vp_line_dir.x));
float scale_max_y = min(1.0, 0.99 * (1.0 - vp_line_begin.y) / max(1e-5, vp_line_dir.y));
float scale_min_x = min(1.0, 0.99 * vp_line_begin.x / max(1e-5, -vp_line_dir.x));
float scale_min_y = min(1.0, 0.99 * vp_line_begin.y / max(1e-5, -vp_line_dir.y));
float line_clip = min(scale_max_x, scale_max_y) * min(scale_min_x, scale_min_y);
line_dir *= line_clip;
z_dir *= line_clip;
w_dir *= line_clip;
// clip z and w advance to line advance
vec2 line_advance = normalize(line_dir); // down to pixel
float step_size = length(line_advance) / length(line_dir);
float z_advance = z_dir * step_size; // adapt z advance to line advance
float w_advance = w_dir * step_size; // adapt w advance to line advance
// make line advance faster if direction is closer to pixel edges (this avoids sampling the same pixel twice)
float advance_angle_adj = 1.0 / max(abs(line_advance.x), abs(line_advance.y));
line_advance *= advance_angle_adj; // adapt z advance to line advance
z_advance *= advance_angle_adj;
w_advance *= advance_angle_adj;
vec2 pos = line_begin;
float z = z_begin;
float w = w_begin;
float z_from = z / w;
float z_to = z_from;
float depth;
vec2 prev_pos = pos;
bool found = false;
float steps_taken = 0.0;
for (int i = 0; i < num_steps; i++) {
pos += line_advance;
z += z_advance;
w += w_advance;
// convert to linear depth
depth = texture(source_depth, pos * pixel_size).r * 2.0 - 1.0;
#ifdef USE_ORTHOGONAL_PROJECTION
depth = ((depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
#else
depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
#endif
depth = -depth;
z_from = z_to;
z_to = z / w;
if (depth > z_to) {
// if depth was surpassed
if (depth <= max(z_to, z_from) + depth_tolerance) {
// check the depth tolerance
found = true;
}
break;
}
steps_taken += 1.0;
prev_pos = pos;
}
if (found) {
float margin_blend = 1.0;
vec2 margin = vec2((viewport_size.x + viewport_size.y) * 0.5 * 0.05); // make a uniform margin
if (any(bvec4(lessThan(pos, -margin), greaterThan(pos, viewport_size + margin)))) {
// clip outside screen + margin
frag_color = vec4(0.0);
return;
}
{
//blend fading out towards external margin
vec2 margin_grad = mix(pos - viewport_size, -pos, lessThan(pos, vec2(0.0)));
margin_blend = 1.0 - smoothstep(0.0, margin.x, max(margin_grad.x, margin_grad.y));
//margin_blend = 1.0;
}
vec2 final_pos;
float grad;
grad = steps_taken / float(num_steps);
float initial_fade = curve_fade_in == 0.0 ? 1.0 : pow(clamp(grad, 0.0, 1.0), curve_fade_in);
float fade = pow(clamp(1.0 - grad, 0.0, 1.0), distance_fade) * initial_fade;
final_pos = pos;
#ifdef REFLECT_ROUGHNESS
vec4 final_color;
// if roughness is enabled, do screen space cone tracing
if (roughness > 0.001) {
///////////////////////////////////////////////////////////////////////////////////////
// use a blurred version (in consecutive mipmaps) of the screen to simulate roughness
float gloss = 1.0 - roughness;
float cone_angle = roughness * M_PI * 0.5;
vec2 cone_dir = final_pos - line_begin;
float cone_len = length(cone_dir);
cone_dir = normalize(cone_dir); // will be used normalized from now on
float max_mipmap = filter_mipmap_levels - 1.0;
float gloss_mult = gloss;
float rem_alpha = 1.0;
final_color = vec4(0.0);
for (int i = 0; i < 7; i++) {
float op_len = 2.0 * tan(cone_angle) * cone_len; // opposite side of iso triangle
float radius;
{
// fit to sphere inside cone (sphere ends at end of cone), something like this:
// ___
// \O/
// V
//
// as it avoids bleeding from beyond the reflection as much as possible. As a plus
// it also makes the rough reflection more elongated.
float a = op_len;
float h = cone_len;
float a2 = a * a;
float fh2 = 4.0f * h * h;
radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h);
}
// find the place where screen must be sampled
vec2 sample_pos = (line_begin + cone_dir * (cone_len - radius)) * pixel_size;
// radius is in pixels, so it's natural that log2(radius) maps to the right mipmap for the amount of pixels
float mipmap = clamp(log2(radius), 0.0, max_mipmap);
//mipmap = max(mipmap - 1.0, 0.0);
// do sampling
vec4 sample_color;
{
sample_color = textureLod(source_diffuse, sample_pos, mipmap);
}
// multiply by gloss
sample_color.rgb *= gloss_mult;
sample_color.a = gloss_mult;
rem_alpha -= sample_color.a;
if (rem_alpha < 0.0) {
sample_color.rgb *= (1.0 - abs(rem_alpha));
}
final_color += sample_color;
if (final_color.a >= 0.95) {
// This code of accumulating gloss and aborting on near one
// makes sense when you think of cone tracing.
// Think of it as if roughness was 0, then we could abort on the first
// iteration. For lesser roughness values, we need more iterations, but
// each needs to have less influence given the sphere is smaller
break;
}
cone_len -= radius * 2.0; // go to next (smaller) circle.
gloss_mult *= gloss;
}
} else {
final_color = textureLod(source_diffuse, final_pos * pixel_size, 0.0);
}
frag_color = vec4(final_color.rgb, fade * margin_blend);
#else
frag_color = vec4(textureLod(source_diffuse, final_pos * pixel_size, 0.0).rgb, fade * margin_blend);
#endif
} else {
frag_color = vec4(0.0, 0.0, 0.0, 0.0);
}
}

View file

@ -1,277 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 vertex_attrib;
/* clang-format on */
void main() {
gl_Position = vertex_attrib;
gl_Position.z = 1.0;
}
/* clang-format off */
[fragment]
#define TWO_PI 6.283185307179586476925286766559
#ifdef SSAO_QUALITY_HIGH
#define NUM_SAMPLES (16)
#endif
#ifdef SSAO_QUALITY_LOW
#define NUM_SAMPLES (8)
#endif
#if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH)
#define NUM_SAMPLES (12)
#endif
// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower
// miplevel to maintain reasonable spatial locality in the cache
// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing.
// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively
#define LOG_MAX_OFFSET (3)
// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp
#define MAX_MIP_LEVEL (4)
// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent
// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9
const int ROTATIONS[] = int[](
1, 1, 2, 3, 2, 5, 2, 3, 2,
3, 3, 5, 5, 3, 4, 7, 5, 5, 7,
9, 8, 5, 5, 7, 7, 7, 8, 5, 8,
11, 12, 7, 10, 13, 8, 11, 8, 7, 14,
11, 11, 13, 12, 13, 19, 17, 13, 11, 18,
19, 11, 11, 14, 17, 21, 15, 16, 17, 18,
13, 17, 11, 17, 19, 18, 25, 18, 19, 19,
29, 21, 19, 27, 31, 29, 21, 18, 17, 29,
31, 31, 23, 18, 25, 26, 25, 23, 19, 34,
19, 27, 21, 25, 39, 29, 17, 21, 27);
/* clang-format on */
//#define NUM_SPIRAL_TURNS (7)
const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES - 1];
uniform sampler2D source_depth; //texunit:0
uniform highp usampler2D source_depth_mipmaps; //texunit:1
uniform sampler2D source_normal; //texunit:2
uniform ivec2 screen_size;
uniform float camera_z_far;
uniform float camera_z_near;
uniform float intensity_div_r6;
uniform float radius;
#ifdef ENABLE_RADIUS2
uniform float intensity_div_r62;
uniform float radius2;
#endif
uniform float bias;
uniform float proj_scale;
layout(location = 0) out float visibility;
uniform vec4 proj_info;
vec3 reconstructCSPosition(vec2 S, float z) {
#ifdef USE_ORTHOGONAL_PROJECTION
return vec3((S.xy * proj_info.xy + proj_info.zw), z);
#else
return vec3((S.xy * proj_info.xy + proj_info.zw) * z, z);
#endif
}
vec3 getPosition(ivec2 ssP) {
vec3 P;
P.z = texelFetch(source_depth, ssP, 0).r;
P.z = P.z * 2.0 - 1.0;
#ifdef USE_ORTHOGONAL_PROJECTION
P.z = ((P.z + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
#else
P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near));
#endif
P.z = -P.z;
// Offset to pixel center
P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
return P;
}
/** Reconstructs screen-space unit normal from screen-space position */
vec3 reconstructCSFaceNormal(vec3 C) {
return normalize(cross(dFdy(C), dFdx(C)));
}
/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */
vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR) {
// Radius relative to ssR
float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES));
float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle;
ssR = alpha;
return vec2(cos(angle), sin(angle));
}
/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */
vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) {
// Derivation:
// mipLevel = floor(log(ssR / MAX_OFFSET));
int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL);
ivec2 ssP = ivec2(ssR * unitOffset) + ssC;
vec3 P;
// We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map.
// Manually clamp to the texture size because texelFetch bypasses the texture unit
ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (screen_size >> mipLevel) - ivec2(1));
if (mipLevel < 1) {
//read from depth buffer
P.z = texelFetch(source_depth, mipP, 0).r;
P.z = P.z * 2.0 - 1.0;
#ifdef USE_ORTHOGONAL_PROJECTION
P.z = ((P.z + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
#else
P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near));
#endif
P.z = -P.z;
} else {
//read from mipmaps
uint d = texelFetch(source_depth_mipmaps, mipP, mipLevel - 1).r;
P.z = -(float(d) / 65535.0) * camera_z_far;
}
// Offset to pixel center
P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
return P;
}
/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds
to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius
Note that units of H() in the HPG12 paper are meters, not
unitless. The whole falloff/sampling function is therefore
unitless. In this implementation, we factor out (9 / radius).
Four versions of the falloff function are implemented below
*/
float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in float p_radius, in int tapIndex, in float randomPatternRotationAngle) {
// Offset on the unit disk, spun for this pixel
float ssR;
vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR);
ssR *= ssDiskRadius;
// The occluding point in camera space
vec3 Q = getOffsetPosition(ssC, unitOffset, ssR);
vec3 v = Q - C;
float vv = dot(v, v);
float vn = dot(v, n_C);
const float epsilon = 0.01;
float radius2 = p_radius * p_radius;
// A: From the HPG12 paper
// Note large epsilon to avoid overdarkening within cracks
//return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6;
// B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended]
float f = max(radius2 - vv, 0.0);
return f * f * f * max((vn - bias) / (epsilon + vv), 0.0);
// C: Medium contrast (which looks better at high radii), no division. Note that the
// contribution still falls off with radius^2, but we've adjusted the rate in a way that is
// more computationally efficient and happens to be aesthetically pleasing.
// return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0);
// D: Low contrast, no division operation
// return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0);
}
void main() {
// Pixel being shaded
ivec2 ssC = ivec2(gl_FragCoord.xy);
// World space point being shaded
vec3 C = getPosition(ssC);
/*
if (C.z <= -camera_z_far * 0.999) {
// We're on the skybox
visibility=1.0;
return;
}
*/
//visibility = -C.z / camera_z_far;
//return;
#if 0
vec3 n_C = texelFetch(source_normal, ssC, 0).rgb * 2.0 - 1.0;
#else
vec3 n_C = reconstructCSFaceNormal(C);
n_C = -n_C;
#endif
// Hash function used in the HPG12 AlchemyAO paper
float randomPatternRotationAngle = mod(float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10), TWO_PI);
// Reconstruct normals from positions. These will lead to 1-pixel black lines
// at depth discontinuities, however the blur will wipe those out so they are not visible
// in the final image.
// Choose the screen-space sample radius
// proportional to the projected area of the sphere
#ifdef USE_ORTHOGONAL_PROJECTION
float ssDiskRadius = -proj_scale * radius;
#else
float ssDiskRadius = -proj_scale * radius / C.z;
#endif
float sum = 0.0;
for (int i = 0; i < NUM_SAMPLES; ++i) {
sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius, i, randomPatternRotationAngle);
}
float A = max(0.0, 1.0 - sum * intensity_div_r6 * (5.0 / float(NUM_SAMPLES)));
#ifdef ENABLE_RADIUS2
//go again for radius2
randomPatternRotationAngle = mod(float((5 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 11), TWO_PI);
// Reconstruct normals from positions. These will lead to 1-pixel black lines
// at depth discontinuities, however the blur will wipe those out so they are not visible
// in the final image.
// Choose the screen-space sample radius
// proportional to the projected area of the sphere
ssDiskRadius = -proj_scale * radius2 / C.z;
sum = 0.0;
for (int i = 0; i < NUM_SAMPLES; ++i) {
sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius2, i, randomPatternRotationAngle);
}
A = min(A, max(0.0, 1.0 - sum * intensity_div_r62 * (5.0 / float(NUM_SAMPLES))));
#endif
// Bilateral box-filter over a quad for free, respecting depth edges
// (the difference that this makes is subtle)
if (abs(dFdx(C.z)) < 0.02) {
A -= dFdx(A) * (float(ssC.x & 1) - 0.5);
}
if (abs(dFdy(C.z)) < 0.02) {
A -= dFdy(A) * (float(ssC.y & 1) - 0.5);
}
visibility = A;
}

View file

@ -1,119 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 vertex_attrib;
/* clang-format on */
void main() {
gl_Position = vertex_attrib;
gl_Position.z = 1.0;
}
/* clang-format off */
[fragment]
uniform sampler2D source_ssao; //texunit:0
/* clang-format on */
uniform sampler2D source_depth; //texunit:1
uniform sampler2D source_normal; //texunit:3
layout(location = 0) out float visibility;
//////////////////////////////////////////////////////////////////////////////////////////////
// Tunable Parameters:
/** Increase to make depth edges crisper. Decrease to reduce flicker. */
uniform float edge_sharpness;
/** Step in 2-pixel intervals since we already blurred against neighbors in the
first AO pass. This constant can be increased while R decreases to improve
performance at the expense of some dithering artifacts.
Morgan found that a scale of 3 left a 1-pixel checkerboard grid that was
unobjectionable after shading was applied but eliminated most temporal incoherence
from using small numbers of sample taps.
*/
uniform int filter_scale;
/** Filter radius in pixels. This will be multiplied by SCALE. */
#define R (4)
//////////////////////////////////////////////////////////////////////////////////////////////
// Gaussian coefficients
const float gaussian[R + 1] =
//float[](0.356642, 0.239400, 0.072410, 0.009869);
//float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0
float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0
//float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0
/** (1, 0) or (0, 1) */
uniform ivec2 axis;
uniform float camera_z_far;
uniform float camera_z_near;
uniform ivec2 screen_size;
void main() {
ivec2 ssC = ivec2(gl_FragCoord.xy);
float depth = texelFetch(source_depth, ssC, 0).r;
//vec3 normal = texelFetch(source_normal, ssC, 0).rgb * 2.0 - 1.0;
depth = depth * 2.0 - 1.0;
depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
float depth_divide = 1.0 / camera_z_far;
//depth *= depth_divide;
/*
if (depth > camera_z_far * 0.999) {
discard; //skybox
}
*/
float sum = texelFetch(source_ssao, ssC, 0).r;
// Base weight for depth falloff. Increase this for more blurriness,
// decrease it for better edge discrimination
float BASE = gaussian[0];
float totalWeight = BASE;
sum *= totalWeight;
ivec2 clamp_limit = screen_size - ivec2(1);
for (int r = -R; r <= R; ++r) {
// We already handled the zero case above. This loop should be unrolled and the static branch optimized out,
// so the IF statement has no runtime cost
if (r != 0) {
ivec2 ppos = ssC + axis * (r * filter_scale);
float value = texelFetch(source_ssao, clamp(ppos, ivec2(0), clamp_limit), 0).r;
ivec2 rpos = clamp(ppos, ivec2(0), clamp_limit);
float temp_depth = texelFetch(source_depth, rpos, 0).r;
//vec3 temp_normal = texelFetch(source_normal, rpos, 0).rgb * 2.0 - 1.0;
temp_depth = temp_depth * 2.0 - 1.0;
temp_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - temp_depth * (camera_z_far - camera_z_near));
//temp_depth *= depth_divide;
// spatial domain: offset gaussian tap
float weight = 0.3 + gaussian[abs(r)];
//weight *= max(0.0, dot(temp_normal, normal));
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
weight *= max(0.0, 1.0 - edge_sharpness * abs(temp_depth - depth));
sum += value * weight;
totalWeight += weight;
}
}
const float epsilon = 0.0001;
visibility = sum / (totalWeight + epsilon);
}

View file

@ -1,56 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 vertex_attrib;
/* clang-format on */
void main() {
gl_Position = vertex_attrib;
}
/* clang-format off */
[fragment]
#ifdef MINIFY_START
#define SDEPTH_TYPE highp sampler2D
uniform float camera_z_far;
/* clang-format on */
uniform float camera_z_near;
#else
#define SDEPTH_TYPE mediump usampler2D
#endif
uniform SDEPTH_TYPE source_depth; //texunit:0
uniform ivec2 from_size;
uniform int source_mipmap;
layout(location = 0) out mediump uint depth;
void main() {
ivec2 ssP = ivec2(gl_FragCoord.xy);
// Rotated grid subsampling to avoid XY directional bias or Z precision bias while downsampling.
// On DX9, the bit-and can be implemented with floating-point modulo
#ifdef MINIFY_START
float fdepth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r;
fdepth = fdepth * 2.0 - 1.0;
#ifdef USE_ORTHOGONAL_PROJECTION
fdepth = ((fdepth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
#else
fdepth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - fdepth * (camera_z_far - camera_z_near));
#endif
fdepth /= camera_z_far;
depth = uint(clamp(fdepth * 65535.0, 0.0, 65535.0));
#else
depth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r;
#endif
}

View file

@ -1,174 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 vertex_attrib;
/* clang-format on */
layout(location = 4) in vec2 uv_in;
out vec2 uv_interp;
void main() {
uv_interp = uv_in;
gl_Position = vertex_attrib;
}
/* clang-format off */
[fragment]
//#define QUALIFIER uniform // some guy on the interweb says it may be faster with this
#define QUALIFIER const
#ifdef USE_25_SAMPLES
const int kernel_size = 25;
/* clang-format on */
QUALIFIER vec2 kernel[25] = vec2[](
vec2(0.530605, 0.0),
vec2(0.000973794, -3.0),
vec2(0.00333804, -2.52083),
vec2(0.00500364, -2.08333),
vec2(0.00700976, -1.6875),
vec2(0.0094389, -1.33333),
vec2(0.0128496, -1.02083),
vec2(0.017924, -0.75),
vec2(0.0263642, -0.520833),
vec2(0.0410172, -0.333333),
vec2(0.0493588, -0.1875),
vec2(0.0402784, -0.0833333),
vec2(0.0211412, -0.0208333),
vec2(0.0211412, 0.0208333),
vec2(0.0402784, 0.0833333),
vec2(0.0493588, 0.1875),
vec2(0.0410172, 0.333333),
vec2(0.0263642, 0.520833),
vec2(0.017924, 0.75),
vec2(0.0128496, 1.02083),
vec2(0.0094389, 1.33333),
vec2(0.00700976, 1.6875),
vec2(0.00500364, 2.08333),
vec2(0.00333804, 2.52083),
vec2(0.000973794, 3.0));
#endif //USE_25_SAMPLES
#ifdef USE_17_SAMPLES
const int kernel_size = 17;
QUALIFIER vec2 kernel[17] = vec2[](
vec2(0.536343, 0.0),
vec2(0.00317394, -2.0),
vec2(0.0100386, -1.53125),
vec2(0.0144609, -1.125),
vec2(0.0216301, -0.78125),
vec2(0.0347317, -0.5),
vec2(0.0571056, -0.28125),
vec2(0.0582416, -0.125),
vec2(0.0324462, -0.03125),
vec2(0.0324462, 0.03125),
vec2(0.0582416, 0.125),
vec2(0.0571056, 0.28125),
vec2(0.0347317, 0.5),
vec2(0.0216301, 0.78125),
vec2(0.0144609, 1.125),
vec2(0.0100386, 1.53125),
vec2(0.00317394, 2.0));
#endif //USE_17_SAMPLES
#ifdef USE_11_SAMPLES
const int kernel_size = 11;
QUALIFIER vec2 kernel[11] = vec2[](
vec2(0.560479, 0.0),
vec2(0.00471691, -2.0),
vec2(0.0192831, -1.28),
vec2(0.03639, -0.72),
vec2(0.0821904, -0.32),
vec2(0.0771802, -0.08),
vec2(0.0771802, 0.08),
vec2(0.0821904, 0.32),
vec2(0.03639, 0.72),
vec2(0.0192831, 1.28),
vec2(0.00471691, 2.0));
#endif //USE_11_SAMPLES
uniform float max_radius;
uniform float camera_z_far;
uniform float camera_z_near;
uniform float unit_size;
uniform vec2 dir;
in vec2 uv_interp;
uniform sampler2D source_diffuse; //texunit:0
uniform sampler2D source_sss; //texunit:1
uniform sampler2D source_depth; //texunit:2
layout(location = 0) out vec4 frag_color;
void main() {
float strength = texture(source_sss, uv_interp).r;
strength *= strength; //stored as sqrt
// Fetch color of current pixel:
vec4 base_color = texture(source_diffuse, uv_interp);
if (strength > 0.0) {
// Fetch linear depth of current pixel:
float depth = texture(source_depth, uv_interp).r * 2.0 - 1.0;
#ifdef USE_ORTHOGONAL_PROJECTION
depth = ((depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
float scale = unit_size; //remember depth is negative by default in OpenGL
#else
depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
float scale = unit_size / depth; //remember depth is negative by default in OpenGL
#endif
// Calculate the final step to fetch the surrounding pixels:
vec2 step = max_radius * scale * dir;
step *= strength; // Modulate it using the alpha channel.
step *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3.
// Accumulate the center sample:
vec3 color_accum = base_color.rgb;
color_accum *= kernel[0].x;
#ifdef ENABLE_STRENGTH_WEIGHTING
float color_weight = kernel[0].x;
#endif
// Accumulate the other samples:
for (int i = 1; i < kernel_size; i++) {
// Fetch color and depth for current sample:
vec2 offset = uv_interp + kernel[i].y * step;
vec3 color = texture(source_diffuse, offset).rgb;
#ifdef ENABLE_FOLLOW_SURFACE
// If the difference in depth is huge, we lerp color back to "colorM":
float depth_cmp = texture(source_depth, offset).r * 2.0 - 1.0;
#ifdef USE_ORTHOGONAL_PROJECTION
depth_cmp = ((depth_cmp + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
#else
depth_cmp = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth_cmp * (camera_z_far - camera_z_near));
#endif
float s = clamp(300.0f * scale * max_radius * abs(depth - depth_cmp), 0.0, 1.0);
color = mix(color, base_color.rgb, s);
#endif
// Accumulate:
color *= kernel[i].x;
#ifdef ENABLE_STRENGTH_WEIGHTING
float color_s = texture(source_sss, offset).r;
color_weight += color_s * kernel[i].x;
color *= color_s;
#endif
color_accum += color;
}
#ifdef ENABLE_STRENGTH_WEIGHTING
color_accum /= color_weight;
#endif
frag_color = vec4(color_accum, base_color.a); //keep alpha (used for SSAO)
} else {
frag_color = base_color;
}
}

View file

@ -1,309 +0,0 @@
/* clang-format off */
[vertex]
layout(location = 0) in highp vec4 vertex_attrib;
/* clang-format on */
layout(location = 4) in vec2 uv_in;
out vec2 uv_interp;
void main() {
gl_Position = vertex_attrib;
uv_interp = uv_in;
#ifdef V_FLIP
uv_interp.y = 1.0f - uv_interp.y;
#endif
}
/* clang-format off */
[fragment]
#if !defined(GLES_OVER_GL)
precision mediump float;
#endif
/* clang-format on */
in vec2 uv_interp;
uniform highp sampler2D source; //texunit:0
uniform float exposure;
uniform float white;
#ifdef USE_AUTO_EXPOSURE
uniform highp sampler2D source_auto_exposure; //texunit:1
uniform highp float auto_exposure_grey;
#endif
#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7)
#define USING_GLOW // only use glow when at least one glow level is selected
uniform highp sampler2D source_glow; //texunit:2
uniform highp float glow_intensity;
#endif
#ifdef USE_BCS
uniform vec3 bcs;
#endif
#ifdef USE_COLOR_CORRECTION
uniform sampler2D color_correction; //texunit:3
#endif
layout(location = 0) out vec4 frag_color;
#ifdef USE_GLOW_FILTER_BICUBIC
// w0, w1, w2, and w3 are the four cubic B-spline basis functions
float w0(float a) {
return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f);
}
float w1(float a) {
return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f);
}
float w2(float a) {
return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f);
}
float w3(float a) {
return (1.0f / 6.0f) * (a * a * a);
}
// g0 and g1 are the two amplitude functions
float g0(float a) {
return w0(a) + w1(a);
}
float g1(float a) {
return w2(a) + w3(a);
}
// h0 and h1 are the two offset functions
float h0(float a) {
return -1.0f + w1(a) / (w0(a) + w1(a));
}
float h1(float a) {
return 1.0f + w3(a) / (w2(a) + w3(a));
}
uniform ivec2 glow_texture_size;
vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
float lod = float(p_lod);
vec2 tex_size = vec2(glow_texture_size >> p_lod);
vec2 pixel_size = vec2(1.0f) / tex_size;
uv = uv * tex_size + vec2(0.5f);
vec2 iuv = floor(uv);
vec2 fuv = fract(uv);
float g0x = g0(fuv.x);
float g1x = g1(fuv.x);
float h0x = h0(fuv.x);
float h1x = h1(fuv.x);
float h0y = h0(fuv.y);
float h1y = h1(fuv.y);
vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5f)) * pixel_size;
vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5f)) * pixel_size;
vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5f)) * pixel_size;
vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5f)) * pixel_size;
return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) +
(g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod)));
}
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod)
#else
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod))
#endif
vec3 tonemap_filmic(vec3 color, float white) {
// exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers
// also useful to scale the input to the range that the tonemapper is designed for (some require very high input values)
// has no effect on the curve's general shape or visual properties
const float exposure_bias = 2.0f;
const float A = 0.22f * exposure_bias * exposure_bias; // bias baked into constants for performance
const float B = 0.30f * exposure_bias;
const float C = 0.10f;
const float D = 0.20f;
const float E = 0.01f;
const float F = 0.30f;
vec3 color_tonemapped = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F;
float white_tonemapped = ((white * (A * white + C * B) + D * E) / (white * (A * white + B) + D * F)) - E / F;
return clamp(color_tonemapped / white_tonemapped, vec3(0.0f), vec3(1.0f));
}
vec3 tonemap_aces(vec3 color, float white) {
const float exposure_bias = 0.85f;
const float A = 2.51f * exposure_bias * exposure_bias;
const float B = 0.03f * exposure_bias;
const float C = 2.43f * exposure_bias * exposure_bias;
const float D = 0.59f * exposure_bias;
const float E = 0.14f;
vec3 color_tonemapped = (color * (A * color + B)) / (color * (C * color + D) + E);
float white_tonemapped = (white * (A * white + B)) / (white * (C * white + D) + E);
return clamp(color_tonemapped / white_tonemapped, vec3(0.0f), vec3(1.0f));
}
vec3 tonemap_reinhard(vec3 color, float white) {
return clamp((white * color + color) / (color * white + white), vec3(0.0f), vec3(1.0f));
}
vec3 linear_to_srgb(vec3 color) { // convert linear rgb to srgb, assumes clamped input in range [0;1]
const vec3 a = vec3(0.055f);
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
}
// inputs are LINEAR, If Linear tonemapping is selected no transform is performed else outputs are clamped [0, 1] color
vec3 apply_tonemapping(vec3 color, float white) {
#ifdef USE_REINHARD_TONEMAPPER
return tonemap_reinhard(color, white);
#endif
#ifdef USE_FILMIC_TONEMAPPER
return tonemap_filmic(color, white);
#endif
#ifdef USE_ACES_TONEMAPPER
return tonemap_aces(color, white);
#endif
return color; // no other selected -> linear: no color transform applied
}
vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels
vec3 glow = vec3(0.0f);
#ifdef USE_GLOW_LEVEL1
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb;
#endif
#ifdef USE_GLOW_LEVEL2
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb;
#endif
#ifdef USE_GLOW_LEVEL3
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb;
#endif
#ifdef USE_GLOW_LEVEL4
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb;
#endif
#ifdef USE_GLOW_LEVEL5
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb;
#endif
#ifdef USE_GLOW_LEVEL6
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb;
#endif
#ifdef USE_GLOW_LEVEL7
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 7).rgb;
#endif
return glow;
}
vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blending mode
#ifdef USE_GLOW_REPLACE
color = glow;
#endif
#ifdef USE_GLOW_SCREEN
//need color clamping
color = clamp(color, vec3(0.0f), vec3(1.0f));
color = max((color + glow) - (color * glow), vec3(0.0));
#endif
#ifdef USE_GLOW_SOFTLIGHT
//need color clamping
color = clamp(color, vec3(0.0f), vec3(1.0));
glow = glow * vec3(0.5f) + vec3(0.5f);
color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r)));
color.g = (glow.g <= 0.5f) ? (color.g - (1.0f - 2.0f * glow.g) * color.g * (1.0f - color.g)) : (((glow.g > 0.5f) && (color.g <= 0.25f)) ? (color.g + (2.0f * glow.g - 1.0f) * (4.0f * color.g * (4.0f * color.g + 1.0f) * (color.g - 1.0f) + 7.0f * color.g)) : (color.g + (2.0f * glow.g - 1.0f) * (sqrt(color.g) - color.g)));
color.b = (glow.b <= 0.5f) ? (color.b - (1.0f - 2.0f * glow.b) * color.b * (1.0f - color.b)) : (((glow.b > 0.5f) && (color.b <= 0.25f)) ? (color.b + (2.0f * glow.b - 1.0f) * (4.0f * color.b * (4.0f * color.b + 1.0f) * (color.b - 1.0f) + 7.0f * color.b)) : (color.b + (2.0f * glow.b - 1.0f) * (sqrt(color.b) - color.b)));
#endif
#if !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) && !defined(USE_GLOW_REPLACE) // no other selected -> additive
color += glow;
#endif
return color;
}
vec3 apply_bcs(vec3 color, vec3 bcs) {
color = mix(vec3(0.0f), color, bcs.x);
color = mix(vec3(0.5f), color, bcs.y);
color = mix(vec3(dot(vec3(1.0f), color) * 0.33333f), color, bcs.z);
return color;
}
vec3 apply_color_correction(vec3 color, sampler2D correction_tex) {
color.r = texture(correction_tex, vec2(color.r, 0.0f)).r;
color.g = texture(correction_tex, vec2(color.g, 0.0f)).g;
color.b = texture(correction_tex, vec2(color.b, 0.0f)).b;
return color;
}
void main() {
vec3 color = textureLod(source, uv_interp, 0.0f).rgb;
// Exposure
#ifdef USE_AUTO_EXPOSURE
color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / auto_exposure_grey;
#endif
color *= exposure;
// Early Tonemap & SRGB Conversion; note that Linear tonemapping does not clamp to [0, 1]; some operations below expect a [0, 1] range and will clamp
color = apply_tonemapping(color, white);
#ifdef KEEP_3D_LINEAR
// leave color as is (-> don't convert to SRGB)
#else
//need color clamping
color = clamp(color, vec3(0.0f), vec3(1.0f));
color = linear_to_srgb(color); // regular linear -> SRGB conversion (needs clamped values)
#endif
// Glow
#ifdef USING_GLOW
vec3 glow = gather_glow(source_glow, uv_interp) * glow_intensity;
// high dynamic range -> SRGB
glow = apply_tonemapping(glow, white);
glow = clamp(glow, vec3(0.0f), vec3(1.0f));
glow = linear_to_srgb(glow);
color = apply_glow(color, glow);
#endif
// Additional effects
#ifdef USE_BCS
color = apply_bcs(color, bcs);
#endif
#ifdef USE_COLOR_CORRECTION
color = apply_color_correction(color, color_correction);
#endif
frag_color = vec4(color, 1.0f);
}

View file

@ -1245,23 +1245,14 @@ void EditorExport::add_export_preset(const Ref<EditorExportPreset> &p_preset, in
String EditorExportPlatform::test_etc2() const {
String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name");
bool driver_fallback = ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2");
bool etc_supported = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc");
bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc2");
if (driver == "GLES2" && !etc_supported) {
return TTR("Target platform requires 'ETC' texture compression for GLES2. Enable 'Import Etc' in Project Settings.");
} else if (driver == "GLES3") {
String err;
if (!etc2_supported) {
err += TTR("Target platform requires 'ETC2' texture compression for GLES3. Enable 'Import Etc 2' in Project Settings.");
}
if (driver_fallback && !etc_supported) {
if (err != String())
err += "\n";
err += TTR("Target platform requires 'ETC' texture compression for the driver fallback to GLES2.\nEnable 'Import Etc' in Project Settings, or disable 'Driver Fallback Enabled'.");
}
return err;
} else if (driver == "Vulkan" && !etc2_supported) {
// FIXME: Review if this is true for Vulkan.
return TTR("Target platform requires 'ETC2' texture compression for Vulkan. Enable 'Import Etc 2' in Project Settings.");
}
return String();
}

View file

@ -5353,8 +5353,6 @@ void EditorNode::_update_video_driver_color() {
// TODO: Probably should de-hardcode this and add to editor settings.
if (video_driver->get_text() == "GLES2") {
video_driver->add_color_override("font_color", Color::hex(0x5586a4ff));
} else if (video_driver->get_text() == "GLES3") {
video_driver->add_color_override("font_color", Color::hex(0xa5557dff));
} else if (video_driver->get_text() == "Vulkan") {
video_driver->add_color_override("font_color", theme_base->get_color("vulkan_color", "Editor"));
}

View file

@ -3687,7 +3687,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
view_menu->set_disable_shortcuts(true);
if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
// Alternate display modes only work when using the GLES3 renderer; make this explicit.
// Alternate display modes only work when using the Vulkan renderer; make this explicit.
const int normal_idx = view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL);
const int wireframe_idx = view_menu->get_popup()->get_item_index(VIEW_DISPLAY_WIREFRAME);
const int overdraw_idx = view_menu->get_popup()->get_item_index(VIEW_DISPLAY_OVERDRAW);

View file

@ -484,8 +484,8 @@ private:
if (mode == MODE_NEW) {
ProjectSettings::CustomMap initial_settings;
if (rasterizer_button_group->get_pressed_button()->get_meta("driver_name") == "GLES3") {
initial_settings["rendering/quality/driver/driver_name"] = "GLES3";
if (rasterizer_button_group->get_pressed_button()->get_meta("driver_name") == "Vulkan") {
initial_settings["rendering/quality/driver/driver_name"] = "Vulkan";
} else {
initial_settings["rendering/quality/driver/driver_name"] = "GLES2";
initial_settings["rendering/vram_compression/import_etc2"] = false;
@ -881,7 +881,7 @@ public:
Button *rs_button = memnew(CheckBox);
rs_button->set_button_group(rasterizer_button_group);
rs_button->set_text(TTR("Vulkan"));
rs_button->set_meta("driver_name", "GLES3");
rs_button->set_meta("driver_name", "Vulkan");
rs_button->set_pressed(true);
rvb->add_child(rs_button);
l = memnew(Label);

View file

@ -493,11 +493,6 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs, gles2
fd.close()
def build_gles3_headers(target, source, env):
for x in source:
build_legacygl_header(str(x), include="drivers/gles3/shader_gles3.h", class_suffix="GLES3", output_attribs=True)
def build_gles2_headers(target, source, env):
for x in source:
build_legacygl_header(str(x), include="drivers/gles2/shader_gles2.h", class_suffix="GLES2", output_attribs=True, gles2=True)

View file

@ -689,7 +689,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
editor = true;
#ifdef DEBUG_METHODS_ENABLED
} else if (I->get() == "--gdnative-generate-json-api") {
// Register as an editor instance to use the GLES2 fallback automatically on hardware that doesn't support the GLES3 backend
// Register as an editor instance to use low-end fallback if relevant.
editor = true;
// We still pass it to the main arguments since the argument handling itself is not done in this function
@ -1000,8 +1000,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
video_driver = GLOBAL_GET("rendering/quality/driver/driver_name");
}
GLOBAL_DEF("rendering/quality/driver/fallback_to_gles2", false);
// Assigning here even though it's GLES2-specific, to be sure that it appears in docs
GLOBAL_DEF("rendering/quality/2d/gles2_use_nvidia_rect_flicker_workaround", false);

View file

@ -59,7 +59,7 @@ Password for remote filesystem.
Audio driver ('PulseAudio', 'ALSA', 'Dummy').
.TP
\fB\-\-video\-driver\fR <driver>
Video driver ('GLES3', 'GLES2').
Video driver ('Vulkan', 'GLES2').
.SS "Display options:"
.TP
\fB\-f\fR, \fB\-\-fullscreen\fR

View file

@ -42,7 +42,7 @@ _arguments \
'--remote-fs[use a remote filesystem]:remote filesystem address' \
'--remote-fs-password[password for remote filesystem]:remote filesystem password' \
'--audio-driver[set the audio driver]:audio driver name' \
"--video-driver[set the video driver]:video driver name:((GLES3\:'OpenGL ES 3.0 renderer' GLES2\:'OpenGL ES 2.0 renderer'))" \
"--video-driver[set the video driver]:video driver name:((Vulkan\:'Vulkan renderer' GLES2\:'OpenGL ES 2.0 renderer'))" \
'(-f --fullscreen)'{-f,--fullscreen}'[request fullscreen mode]' \
'(-m --maximized)'{-m,--maximized}'[request a maximized window]' \
'(-w --windowed)'{-w,--windowed}'[request windowed mode]' \

View file

@ -105,7 +105,7 @@ _complete_godot_bash() {
elif [[ $prev == "--video-driver" ]]; then
local IFS=$' \n\t'
# shellcheck disable=SC2207
COMPREPLY=($(compgen -W "GLES3 GLES2" -- "$cur"))
COMPREPLY=($(compgen -W "Vulkan GLES2" -- "$cur"))
elif [[ $prev == "--path" || $prev == "--doctool" ]]; then
local IFS=$'\n\t'
# shellcheck disable=SC2207

View file

@ -424,14 +424,6 @@ void MobileVRInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_t
}
// we don't offset the eye center vertically (yet)
eye_center.y = 0.0;
// unset our render target so we are outputting to our main screen by making RasterizerStorageGLES3::system_fbo our current FBO
#if 0
VSG::rasterizer->set_current_render_target(RID());
// and output
VSG::rasterizer->output_lens_distorted_to_screen(p_render_target, dest, k1, k2, eye_center, oversample);
#endif
}
void MobileVRInterface::process() {

View file

@ -683,8 +683,6 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
int orientation = p_preset->get("screen/orientation");
bool min_gles3 = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name") == "GLES3" &&
!ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2");
bool screen_support_small = p_preset->get("screen/support_small");
bool screen_support_normal = p_preset->get("screen/support_normal");
bool screen_support_large = p_preset->get("screen/support_large");
@ -839,11 +837,6 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
}
}
if (tname == "uses-feature" && attrname == "glEsVersion") {
encode_uint32(min_gles3 ? 0x00030000 : 0x00020000, &p_manifest.write[iofs + 16]);
}
// FIXME: `attr_value != 0xFFFFFFFF` below added as a stopgap measure for GH-32553,
// but the issue should be debugged further and properly addressed.
if (tname == "meta-data" && attrname == "name" && value == "xr_mode_metadata_name") {
@ -1350,11 +1343,10 @@ public:
String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name");
if (driver == "GLES2") {
r_features->push_back("etc");
} else if (driver == "GLES3") {
}
// FIXME: Review what texture formats are used for Vulkan.
if (driver == "Vulkan") {
r_features->push_back("etc2");
if (ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2")) {
r_features->push_back("etc");
}
}
Vector<String> abis = get_enabled_abis(p_preset);

View file

@ -15,7 +15,6 @@
android:largeScreens="true"
android:xlargeScreens="true" />
<!-- glEsVersion is modified by the exporter, changing this value here has no effect. -->
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />

View file

@ -287,8 +287,6 @@ public abstract class Godot extends Activity implements SensorEventListener, IDo
*/
@Keep
private void onVideoInit() {
boolean use_gl3 = getGLESVersionCode() >= 0x00030000;
final FrameLayout layout = new FrameLayout(this);
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
setContentView(layout);
@ -299,7 +297,7 @@ public abstract class Godot extends Activity implements SensorEventListener, IDo
// ...add to FrameLayout
layout.addView(edittext);
mView = new GodotView(this, xrMode, use_gl3, use_32_bits, use_debug_opengl);
mView = new GodotView(this, xrMode, use_32_bits, use_debug_opengl);
layout.addView(mView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
edittext.setView(mView);
io.setEdit(edittext);

View file

@ -73,9 +73,8 @@ public class GodotView extends GLSurfaceView {
private final GestureDetector detector;
private final GodotRenderer godotRenderer;
public GodotView(Godot activity, XRMode xrMode, boolean p_use_gl3, boolean p_use_32_bits, boolean p_use_debug_opengl) {
public GodotView(Godot activity, XRMode xrMode, boolean p_use_32_bits, boolean p_use_debug_opengl) {
super(activity);
GLUtils.use_gl3 = p_use_gl3;
GLUtils.use_32 = p_use_32_bits;
GLUtils.use_debug_opengl = p_use_debug_opengl;

View file

@ -44,7 +44,6 @@ public class GLUtils {
public static final boolean DEBUG = false;
public static boolean use_gl3 = false;
public static boolean use_32 = false;
public static boolean use_debug_opengl = false;

View file

@ -45,6 +45,8 @@ public class RegularConfigChooser implements GLSurfaceView.EGLConfigChooser {
private int[] mValue = new int[1];
// FIXME: Add support for Vulkan.
/* This EGL config specification is used to specify 2.0 rendering.
* We use a minimum size of 4 bits for red/green/blue, but will
* perform actual matching in chooseConfig() below.
@ -59,15 +61,6 @@ public class RegularConfigChooser implements GLSurfaceView.EGLConfigChooser {
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL10.EGL_NONE
};
private static int[] s_configAttribs3 = {
EGL10.EGL_RED_SIZE, 4,
EGL10.EGL_GREEN_SIZE, 4,
EGL10.EGL_BLUE_SIZE, 4,
// EGL10.EGL_DEPTH_SIZE, 16,
// EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //apparently there is no EGL_OPENGL_ES3_BIT
EGL10.EGL_NONE
};
public RegularConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
mRedSize = r;
@ -83,7 +76,7 @@ public class RegularConfigChooser implements GLSurfaceView.EGLConfigChooser {
/* Get the number of minimally matching EGL configurations
*/
int[] num_config = new int[1];
egl.eglChooseConfig(display, GLUtils.use_gl3 ? s_configAttribs3 : s_configAttribs2, null, 0, num_config);
egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
int numConfigs = num_config[0];
@ -94,7 +87,7 @@ public class RegularConfigChooser implements GLSurfaceView.EGLConfigChooser {
/* Allocate then read the array of minimally matching EGL configs
*/
EGLConfig[] configs = new EGLConfig[numConfigs];
egl.eglChooseConfig(display, GLUtils.use_gl3 ? s_configAttribs3 : s_configAttribs2, configs, numConfigs, num_config);
egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
if (GLUtils.DEBUG) {
GLUtils.printConfigs(egl, display, configs);

View file

@ -52,24 +52,17 @@ public class RegularContextFactory implements GLSurfaceView.EGLContextFactory {
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
String driver_name = GodotLib.getGlobal("rendering/quality/driver/driver_name");
if (GLUtils.use_gl3 && !driver_name.equals("GLES3")) {
GLUtils.use_gl3 = false;
}
if (GLUtils.use_gl3)
Log.w(TAG, "creating OpenGL ES 3.0 context :");
else
Log.w(TAG, "creating OpenGL ES 2.0 context :");
// FIXME: Add support for Vulkan.
Log.w(TAG, "creating OpenGL ES 2.0 context :");
GLUtils.checkEglError(TAG, "Before eglCreateContext", egl);
EGLContext context;
if (GLUtils.use_debug_opengl) {
int[] attrib_list2 = { EGL_CONTEXT_CLIENT_VERSION, 2, _EGL_CONTEXT_FLAGS_KHR, _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE };
int[] attrib_list3 = { EGL_CONTEXT_CLIENT_VERSION, 3, _EGL_CONTEXT_FLAGS_KHR, _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE };
context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, GLUtils.use_gl3 ? attrib_list3 : attrib_list2);
context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list2);
} else {
int[] attrib_list2 = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
int[] attrib_list3 = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL10.EGL_NONE };
context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, GLUtils.use_gl3 ? attrib_list3 : attrib_list2);
context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list2);
}
GLUtils.checkEglError(TAG, "After eglCreateContext", egl);
return context;

View file

@ -99,13 +99,6 @@ jobject GodotJavaWrapper::get_class_loader() {
}
}
void GodotJavaWrapper::gfx_init(bool gl2) {
// beats me what this once did, there was no code,
// but we're getting false if our GLES3 driver is initialised
// and true for our GLES2 driver
// Maybe we're supposed to communicate this back or store it?
}
void GodotJavaWrapper::on_video_init(JNIEnv *p_env) {
if (_on_video_init)
if (p_env == NULL)

View file

@ -71,7 +71,6 @@ public:
jobject get_class_loader();
void gfx_init(bool gl2);
void on_video_init(JNIEnv *p_env = NULL);
void restart(JNIEnv *p_env = NULL);
void force_quit(JNIEnv *p_env = NULL);

View file

@ -33,7 +33,6 @@
#include "core/io/file_access_buffered_fa.h"
#include "core/project_settings.h"
#include "drivers/gles2/rasterizer_gles2.h"
#include "drivers/gles3/rasterizer_gles3.h"
#include "drivers/unix/dir_access_unix.h"
#include "drivers/unix/file_access_unix.h"
#include "file_access_android.h"
@ -67,8 +66,6 @@ int OS_Android::get_video_driver_count() const {
const char *OS_Android::get_video_driver_name(int p_driver) const {
switch (p_driver) {
case VIDEO_DRIVER_GLES3:
return "GLES3";
case VIDEO_DRIVER_GLES2:
return "GLES2";
}
@ -123,44 +120,21 @@ int OS_Android::get_current_video_driver() const {
Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
bool use_gl3 = godot_java->get_gles_version_code() >= 0x00030000;
use_gl3 = use_gl3 && (GLOBAL_GET("rendering/quality/driver/driver_name") == "GLES3");
bool gl_initialization_error = false;
while (true) {
if (use_gl3) {
if (RasterizerGLES3::is_viable() == OK) {
godot_java->gfx_init(false);
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
break;
} else {
if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) {
p_video_driver = VIDEO_DRIVER_GLES2;
use_gl3 = false;
continue;
} else {
gl_initialization_error = true;
break;
}
}
} else {
if (RasterizerGLES2::is_viable() == OK) {
godot_java->gfx_init(true);
RasterizerGLES2::register_config();
RasterizerGLES2::make_current();
break;
} else {
gl_initialization_error = true;
break;
}
}
// FIXME: Add Vulkan support. Readd fallback code from Vulkan to GLES2?
if (RasterizerGLES2::is_viable() == OK) {
RasterizerGLES2::register_config();
RasterizerGLES2::make_current();
} else {
gl_initialization_error = true;
}
if (gl_initialization_error) {
OS::get_singleton()->alert("Your device does not support any of the supported OpenGL versions.\n"
"Please try updating your Android version.",
"Unable to initialize Video driver");
"Unable to initialize video driver");
return ERR_UNAVAILABLE;
}
@ -750,7 +724,6 @@ void OS_Android::vibrate_handheld(int p_duration_ms) {
bool OS_Android::_check_internal_feature_support(const String &p_feature) {
if (p_feature == "mobile") {
//TODO support etc2 only if GLES3 driver is selected
return true;
}
#if defined(__aarch64__)

View file

@ -28,10 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "drivers/gles3/rasterizer_gles3.h"
#include "os_haiku.h"
#include "drivers/gles2/rasterizer_gles2.h"
#include "main/main.h"
#include "servers/physics/physics_server_sw.h"
#include "servers/visual/visual_server_raster.h"
@ -78,7 +77,7 @@ int OS_Haiku::get_video_driver_count() const {
}
const char *OS_Haiku::get_video_driver_name(int p_driver) const {
return "GLES3";
return "GLES2";
}
int OS_Haiku::get_current_video_driver() const {
@ -112,9 +111,9 @@ Error OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p
context_gl->initialize();
context_gl->make_current();
context_gl->set_use_vsync(current_video_mode.use_vsync);
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
// FIXME: That's not how the rasterizer setup should happen.
RasterizerGLES2::register_config();
RasterizerGLES2::make_current();
#endif
visual_server = memnew(VisualServerRaster);

View file

@ -33,5 +33,4 @@
// for ifaddrs.h needed in drivers/unix/ip_unix.cpp
#define _BSD_SOURCE 1
#define GLES3_INCLUDE_H "thirdparty/glad/glad/glad.h"
#define GLES2_INCLUDE_H "thirdparty/glad/glad/glad.h"

View file

@ -167,11 +167,9 @@ void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset>
String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name");
if (driver == "GLES2") {
r_features->push_back("etc");
} else if (driver == "GLES3") {
} else if (driver == "Vulkan") {
// FIXME: Review if this is correct.
r_features->push_back("etc2");
if (ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2")) {
r_features->push_back("etc");
}
}
Vector<String> architectures = _get_preset_architectures(p_preset);

View file

@ -47,7 +47,6 @@
@end
*/
bool gles3_available = true;
int gl_view_base_fb;
static String keyboard_text;
static GLView *_instance = NULL;
@ -284,20 +283,11 @@ static void clear_touches() {
kEAGLColorFormatRGBA8,
kEAGLDrawablePropertyColorFormat,
nil];
bool fallback_gl2 = false;
// Create a GL ES 3 context based on the gl driver from project settings
if (GLOBAL_GET("rendering/quality/driver/driver_name") == "GLES3") {
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
NSLog(@"Setting up an OpenGL ES 3.0 context. Based on Project Settings \"rendering/quality/driver/driver_name\"");
if (!context && GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) {
gles3_available = false;
fallback_gl2 = true;
NSLog(@"Failed to create OpenGL ES 3.0 context. Falling back to OpenGL ES 2.0");
}
}
// FIXME: Add Vulkan support via MoltenVK. Add fallback code back?
// Create GL ES 2 context
if (GLOBAL_GET("rendering/quality/driver/driver_name") == "GLES2" || fallback_gl2) {
if (GLOBAL_GET("rendering/quality/driver/driver_name") == "GLES2") {
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
NSLog(@"Setting up an OpenGL ES 2.0 context.");
if (!context) {

View file

@ -33,7 +33,6 @@
#include "os_iphone.h"
#include "drivers/gles2/rasterizer_gles2.h"
#include "drivers/gles3/rasterizer_gles3.h"
#include "servers/visual/visual_server_raster.h"
#include "servers/visual/visual_server_wrap_mt.h"
@ -57,8 +56,6 @@ int OSIPhone::get_video_driver_count() const {
const char *OSIPhone::get_video_driver_name(int p_driver) const {
switch (p_driver) {
case VIDEO_DRIVER_GLES3:
return "GLES3";
case VIDEO_DRIVER_GLES2:
return "GLES2";
}
@ -103,44 +100,22 @@ int OSIPhone::get_current_video_driver() const {
return video_driver_index;
}
extern bool gles3_available; // from gl_view.mm
Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
bool use_gl3 = GLOBAL_GET("rendering/quality/driver/driver_name") == "GLES3";
bool gl_initialization_error = false;
while (true) {
if (use_gl3) {
if (RasterizerGLES3::is_viable() == OK && gles3_available) {
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
break;
} else {
if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) {
p_video_driver = VIDEO_DRIVER_GLES2;
use_gl3 = false;
continue;
} else {
gl_initialization_error = true;
break;
}
}
} else {
if (RasterizerGLES2::is_viable() == OK) {
RasterizerGLES2::register_config();
RasterizerGLES2::make_current();
break;
} else {
gl_initialization_error = true;
break;
}
}
// FIXME: Add Vulkan support via MoltenVK. Add fallback code back?
if (RasterizerGLES2::is_viable() == OK) {
RasterizerGLES2::register_config();
RasterizerGLES2::make_current();
} else {
gl_initialization_error = true;
}
if (gl_initialization_error) {
OS::get_singleton()->alert("Your device does not support any of the supported OpenGL versions.",
"Unable to initialize Video driver");
"Unable to initialize video driver");
return ERR_UNAVAILABLE;
}
@ -155,10 +130,7 @@ Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p
//visual_server->cursor_set_visible(false, 0);
// reset this to what it should be, it will have been set to 0 after visual_server->init() is called
if (use_gl3)
RasterizerStorageGLES3::system_fbo = gl_view_base_fb;
else
RasterizerStorageGLES2::system_fbo = gl_view_base_fb;
RasterizerStorageGLES2::system_fbo = gl_view_base_fb;
AudioDriverManager::initialize(p_audio_driver);
@ -467,7 +439,7 @@ bool OSIPhone::can_draw() const {
int OSIPhone::set_base_framebuffer(int p_fb) {
// gl_view_base_fb has not been updated yet
RasterizerStorageGLES3::system_fbo = p_fb;
RasterizerStorageGLES2::system_fbo = p_fb;
return 0;
};

View file

@ -31,7 +31,6 @@
#include <alloca.h>
#define GLES2_INCLUDE_H <ES2/gl.h>
#define GLES3_INCLUDE_H <ES3/gl.h>
#define PLATFORM_REFCOUNT

View file

@ -271,11 +271,9 @@ void EditorExportPlatformJavaScript::get_preset_features(const Ref<EditorExportP
String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name");
if (driver == "GLES2") {
r_features->push_back("etc");
} else if (driver == "GLES3") {
} else if (driver == "Vulkan") {
// FIXME: Review if this is correct.
r_features->push_back("etc2");
if (ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2")) {
r_features->push_back("etc");
}
}
}
}

View file

@ -32,7 +32,6 @@
#include "core/io/file_access_buffered_fa.h"
#include "drivers/gles2/rasterizer_gles2.h"
#include "drivers/gles3/rasterizer_gles3.h"
#include "drivers/unix/dir_access_unix.h"
#include "drivers/unix/file_access_unix.h"
#include "main/main.h"
@ -825,8 +824,6 @@ int OS_JavaScript::get_video_driver_count() const {
const char *OS_JavaScript::get_video_driver_name(int p_driver) const {
switch (p_driver) {
case VIDEO_DRIVER_GLES3:
return "GLES3";
case VIDEO_DRIVER_GLES2:
return "GLES2";
}
@ -908,41 +905,14 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver,
set_window_per_pixel_transparency_enabled(true);
}
bool gles3 = true;
if (p_video_driver == VIDEO_DRIVER_GLES2) {
gles3 = false;
}
bool gl_initialization_error = false;
while (true) {
if (gles3) {
if (RasterizerGLES3::is_viable() == OK) {
attributes.majorVersion = 2;
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
break;
} else {
if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) {
p_video_driver = VIDEO_DRIVER_GLES2;
gles3 = false;
continue;
} else {
gl_initialization_error = true;
break;
}
}
} else {
if (RasterizerGLES2::is_viable() == OK) {
attributes.majorVersion = 1;
RasterizerGLES2::register_config();
RasterizerGLES2::make_current();
break;
} else {
gl_initialization_error = true;
break;
}
}
if (RasterizerGLES2::is_viable() == OK) {
attributes.majorVersion = 1;
RasterizerGLES2::register_config();
RasterizerGLES2::make_current();
} else {
gl_initialization_error = true;
}
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(GODOT_CANVAS_SELECTOR, &attributes);
@ -951,9 +921,8 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver,
}
if (gl_initialization_error) {
OS::get_singleton()->alert("Your browser does not support any of the supported WebGL versions.\n"
"Please update your browser version.",
"Unable to initialize Video driver");
OS::get_singleton()->alert("Your browser does not seem to support WebGL. Please update your browser version.",
"Unable to initialize video driver");
return ERR_UNAVAILABLE;
}

View file

@ -78,8 +78,6 @@ public:
int key_event_pos;
bool force_quit;
// rasterizer seems to no longer be given to visual server, its using GLES3 directly?
//Rasterizer *rasterizer;
VisualServer *visual_server;
List<String> args;

View file

@ -30,6 +30,5 @@
#include <alloca.h>
#define GLES3_INCLUDE_H "thirdparty/glad/glad/glad.h"
#define GLES2_INCLUDE_H "thirdparty/glad/glad/glad.h"
#define PTHREAD_RENAME_SELF

View file

@ -34,7 +34,6 @@
#include <wrl.h>
// ANGLE doesn't provide a specific lib for GLES3, so we keep using GLES2
#include "GLES2/gl2.h"
#include "os_uwp.h"

View file

@ -45,7 +45,7 @@ class ContextEGL_UWP {
public:
enum Driver {
GLES_2_0,
GLES_3_0,
VULKAN, // FIXME: Add Vulkan support.
};
private:

View file

@ -36,7 +36,6 @@
#include "core/io/marshalls.h"
#include "core/project_settings.h"
#include "drivers/gles2/rasterizer_gles2.h"
#include "drivers/gles3/rasterizer_gles3.h"
#include "drivers/unix/ip_unix.h"
#include "drivers/windows/dir_access_windows.h"
#include "drivers/windows/file_access_windows.h"
@ -186,71 +185,33 @@ Error OS_UWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
main_loop = NULL;
outside = true;
// FIXME: Hardcoded for now, add Vulkan support.
p_video_driver = VIDEO_DRIVER_GLES2;
ContextEGL_UWP::Driver opengl_api_type = ContextEGL_UWP::GLES_2_0;
if (p_video_driver == VIDEO_DRIVER_GLES2) {
opengl_api_type = ContextEGL_UWP::GLES_2_0;
}
bool gl_initialization_error = false;
gl_context = NULL;
while (!gl_context) {
gl_context = memnew(ContextEGL_UWP(window, opengl_api_type));
gl_context = memnew(ContextEGL_UWP(window, opengl_api_type));
if (gl_context->initialize() != OK) {
memdelete(gl_context);
gl_context = NULL;
if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) {
if (p_video_driver == VIDEO_DRIVER_GLES2) {
gl_initialization_error = true;
break;
}
p_video_driver = VIDEO_DRIVER_GLES2;
opengl_api_type = ContextEGL_UWP::GLES_2_0;
} else {
gl_initialization_error = true;
break;
}
}
if (gl_context->initialize() != OK) {
memdelete(gl_context);
gl_context = NULL;
gl_initialization_error = true;
}
while (true) {
if (opengl_api_type == ContextEGL_UWP::GLES_3_0) {
if (RasterizerGLES3::is_viable() == OK) {
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
break;
} else {
if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) {
p_video_driver = VIDEO_DRIVER_GLES2;
opengl_api_type = ContextEGL_UWP::GLES_2_0;
continue;
} else {
gl_initialization_error = true;
break;
}
}
}
if (opengl_api_type == ContextEGL_UWP::GLES_2_0) {
if (RasterizerGLES2::is_viable() == OK) {
RasterizerGLES2::register_config();
RasterizerGLES2::make_current();
break;
} else {
gl_initialization_error = true;
break;
}
if (opengl_api_type == ContextEGL_UWP::GLES_2_0) {
if (RasterizerGLES2::is_viable() == OK) {
RasterizerGLES2::register_config();
RasterizerGLES2::make_current();
} else {
gl_initialization_error = true;
}
}
if (gl_initialization_error) {
OS::get_singleton()->alert("Your video card driver does not support any of the supported OpenGL versions.\n"
"Please update your drivers or if you have a very old or integrated GPU upgrade it.",
"Unable to initialize Video driver");
"Unable to initialize video driver");
return ERR_UNAVAILABLE;
}

View file

@ -29,8 +29,5 @@
/*************************************************************************/
#include <malloc.h>
//#else
//#include <alloca.h>
//#endif
#define GLES3_INCLUDE_H "thirdparty/glad/glad/glad.h"
#define GLES2_INCLUDE_H "thirdparty/glad/glad/glad.h"

View file

@ -166,29 +166,11 @@ Error ContextGL_X11::initialize() {
int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&ctxErrorHandler);
switch (context_type) {
case OLDSTYLE: {
p->glx_context = glXCreateContext(x11_display, vi, 0, GL_TRUE);
ERR_FAIL_COND_V(!p->glx_context, ERR_UNCONFIGURED);
} break;
case GLES_2_0_COMPATIBLE: {
p->glx_context = glXCreateNewContext(x11_display, fbconfig, GLX_RGBA_TYPE, 0, true);
ERR_FAIL_COND_V(!p->glx_context, ERR_UNCONFIGURED);
} break;
case GLES_3_0_COMPATIBLE: {
static int context_attribs[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB /*|GLX_CONTEXT_DEBUG_BIT_ARB*/,
None
};
p->glx_context = glXCreateContextAttribsARB(x11_display, fbconfig, NULL, true, context_attribs);
ERR_FAIL_COND_V(ctxErrorOccurred || !p->glx_context, ERR_UNCONFIGURED);
} break;
}
swa.colormap = XCreateColormap(x11_display, RootWindow(x11_display, vi->screen), vi->visual, AllocNone);

View file

@ -45,15 +45,12 @@ class ContextGL_X11 {
public:
enum ContextType {
OLDSTYLE,
GLES_2_0_COMPATIBLE,
GLES_3_0_COMPATIBLE
};
private:
ContextGL_X11_Private *p;
OS::VideoMode default_video_mode;
//::Colormap x11_colormap;
::Display *x11_display;
::Window &x11_window;
bool double_buffer;

View file

@ -36,5 +36,4 @@
#define PTHREAD_BSD_SET_NAME
#endif
#define GLES3_INCLUDE_H "thirdparty/glad/glad/glad.h"
#define GLES2_INCLUDE_H "thirdparty/glad/glad/glad.h"