Merge pull request #61101 from clayjohn/GLES3-3D

This commit is contained in:
Rémi Verschelde 2022-05-17 12:13:37 +02:00 committed by GitHub
commit d64fc0c114
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1548 additions and 539 deletions

View file

@ -1723,13 +1723,13 @@
<member name="rendering/limits/global_shader_variables/buffer_size" type="int" setter="" getter="" default="65536"> <member name="rendering/limits/global_shader_variables/buffer_size" type="int" setter="" getter="" default="65536">
</member> </member>
<member name="rendering/limits/opengl/max_lights_per_object" type="int" setter="" getter="" default="8"> <member name="rendering/limits/opengl/max_lights_per_object" type="int" setter="" getter="" default="8">
Max number of lights renderable per object. This is further limited by hardware support. Setting this low will slightly reduce memory usage, may decrease shader compile times, and may result in faster rendering on low-end, mobile, or web devices. Max number of omnilights and spotlights renderable per object. At the default value of 8, this means that each surface can be affected by up to 8 omnilights and 8 spotlights. This is further limited by hardware support and [member rendering/limits/opengl/max_renderable_lights]. Setting this low will slightly reduce memory usage, may decrease shader compile times, and may result in faster rendering on low-end, mobile, or web devices.
</member> </member>
<member name="rendering/limits/opengl/max_renderable_elements" type="int" setter="" getter="" default="65536"> <member name="rendering/limits/opengl/max_renderable_elements" type="int" setter="" getter="" default="65536">
Max amount of elements renderable in a frame. If more elements than this are visible per frame, they will not be drawn. Keep in mind elements refer to mesh surfaces and not meshes themselves. Setting this low will slightly reduce memory usage and may decrease shader compile times, particularly on web. For most uses, the default value is suitable, but consider lowering as much as possible on web export. Max amount of elements renderable in a frame. If more elements than this are visible per frame, they will not be drawn. Keep in mind elements refer to mesh surfaces and not meshes themselves. Setting this low will slightly reduce memory usage and may decrease shader compile times, particularly on web. For most uses, the default value is suitable, but consider lowering as much as possible on web export.
</member> </member>
<member name="rendering/limits/opengl/max_renderable_lights" type="int" setter="" getter="" default="256"> <member name="rendering/limits/opengl/max_renderable_lights" type="int" setter="" getter="" default="32">
Max number of lights renderable in a frame. If more lights than this number are used, they will be ignored. Setting this low will slightly reduce memory usage and may decrease shader compile times, particularly on web. For most uses, the default value is suitable, but consider lowering as much as possible on web export. Max number of positional lights renderable in a frame. If more lights than this number are used, they will be ignored. Setting this low will slightly reduce memory usage and may decrease shader compile times, particularly on web. For most uses, the default value is suitable, but consider lowering as much as possible on web export.
</member> </member>
<member name="rendering/limits/spatial_indexer/threaded_cull_minimum_instances" type="int" setter="" getter="" default="1000"> <member name="rendering/limits/spatial_indexer/threaded_cull_minimum_instances" type="int" setter="" getter="" default="1000">
</member> </member>

File diff suppressed because it is too large Load diff

View file

@ -43,6 +43,7 @@
#include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h" #include "servers/rendering_server.h"
#include "shader_gles3.h" #include "shader_gles3.h"
#include "shaders/cubemap_filter.glsl.gen.h"
#include "shaders/sky.glsl.gen.h" #include "shaders/sky.glsl.gen.h"
enum RenderListType { enum RenderListType {
@ -66,17 +67,26 @@ enum SceneUniformLocation {
SCENE_GLOBALS_UNIFORM_LOCATION, SCENE_GLOBALS_UNIFORM_LOCATION,
SCENE_DATA_UNIFORM_LOCATION, SCENE_DATA_UNIFORM_LOCATION,
SCENE_MATERIAL_UNIFORM_LOCATION, SCENE_MATERIAL_UNIFORM_LOCATION,
SCENE_RADIANCE_UNIFORM_LOCATION, SCENE_EMPTY, // Unused, put here to avoid conflicts with SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION.
SCENE_OMNILIGHT_UNIFORM_LOCATION, SCENE_OMNILIGHT_UNIFORM_LOCATION,
SCENE_SPOTLIGHT_UNIFORM_LOCATION, SCENE_SPOTLIGHT_UNIFORM_LOCATION,
SCENE_DIRECTIONAL_LIGHT_UNIFORM_LOCATION,
}; };
enum SkyUniformLocation { enum SkyUniformLocation {
SKY_TONEMAP_UNIFORM_LOCATION, SKY_TONEMAP_UNIFORM_LOCATION,
SKY_GLOBALS_UNIFORM_LOCATION, SKY_GLOBALS_UNIFORM_LOCATION,
SKY_SCENE_DATA_UNIFORM_LOCATION, SKY_EMPTY, // Unused, put here to avoid conflicts with SCENE_DATA_UNIFORM_LOCATION.
SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION,
SKY_MATERIAL_UNIFORM_LOCATION, SKY_MATERIAL_UNIFORM_LOCATION,
SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION,
};
enum {
SPEC_CONSTANT_DISABLE_LIGHTMAP = 0,
SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS = 1,
SPEC_CONSTANT_DISABLE_OMNI_LIGHTS = 2,
SPEC_CONSTANT_DISABLE_SPOT_LIGHTS = 3,
SPEC_CONSTANT_DISABLE_FOG = 4,
}; };
struct RenderDataGLES3 { struct RenderDataGLES3 {
@ -84,6 +94,7 @@ struct RenderDataGLES3 {
bool transparent_bg = false; bool transparent_bg = false;
Transform3D cam_transform = Transform3D(); Transform3D cam_transform = Transform3D();
Transform3D inv_cam_transform = Transform3D();
CameraMatrix cam_projection = CameraMatrix(); CameraMatrix cam_projection = CameraMatrix();
bool cam_orthogonal = false; bool cam_orthogonal = false;
@ -97,14 +108,8 @@ struct RenderDataGLES3 {
const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr; const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr;
const PagedArray<RID> *lights = nullptr; const PagedArray<RID> *lights = nullptr;
const PagedArray<RID> *reflection_probes = nullptr; const PagedArray<RID> *reflection_probes = nullptr;
//const PagedArray<RID> *voxel_gi_instances = nullptr;
//const PagedArray<RID> *decals = nullptr;
//const PagedArray<RID> *lightmaps = nullptr;
//const PagedArray<RID> *fog_volumes = nullptr;
RID environment = RID(); RID environment = RID();
RID camera_effects = RID(); RID camera_effects = RID();
RID shadow_atlas = RID();
RID reflection_atlas = RID();
RID reflection_probe = RID(); RID reflection_probe = RID();
int reflection_probe_pass = 0; int reflection_probe_pass = 0;
@ -113,6 +118,8 @@ struct RenderDataGLES3 {
float screen_mesh_lod_threshold = 0.0; float screen_mesh_lod_threshold = 0.0;
uint32_t directional_light_count = 0; uint32_t directional_light_count = 0;
uint32_t spot_light_count = 0;
uint32_t omni_light_count = 0;
RendererScene::RenderInfo *render_info = nullptr; RendererScene::RenderInfo *render_info = nullptr;
}; };
@ -126,90 +133,81 @@ private:
RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED; RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
uint64_t scene_pass = 0; uint64_t scene_pass = 0;
struct SkyGlobals { template <class T>
RID shader_default_version; struct InstanceSort {
RID default_material; float depth;
RID default_shader; T *instance = nullptr;
RID fog_material; bool operator<(const InstanceSort &p_sort) const {
RID fog_shader; return depth < p_sort.depth;
GLuint quad = 0; }
GLuint quad_array = 0; };
uint32_t max_directional_lights = 4;
uint32_t roughness_layers = 8;
uint32_t ggx_samples = 128;
} sky_globals;
struct SceneGlobals { struct SceneGlobals {
RID shader_default_version; RID shader_default_version;
RID default_material; RID default_material;
RID default_shader; RID default_shader;
RID cubemap_filter_shader_version;
} scene_globals; } scene_globals;
struct SceneState { /* LIGHT INSTANCE */
struct UBO {
float projection_matrix[16];
float inv_projection_matrix[16];
float inv_view_matrix[16];
float view_matrix[16];
float viewport_size[2]; struct LightData {
float screen_pixel_size[2]; float position[3];
float inv_radius;
float ambient_light_color_energy[4]; float direction[3]; // Only used by SpotLight
float size;
float ambient_color_sky_mix; float color[3];
uint32_t ambient_flags; float attenuation;
uint32_t material_uv2_mode;
float opaque_prepass_threshold;
//bool use_ambient_light;
//bool use_ambient_cubemap;
//bool use_reflection_cubemap;
float radiance_inverse_xform[12]; float inv_spot_attenuation;
float cos_spot_angle;
uint32_t directional_light_count; float specular_amount;
float z_far; uint32_t shadow_enabled;
float z_near;
uint32_t pancake_shadows;
uint32_t fog_enabled;
float fog_density;
float fog_height;
float fog_height_density;
float fog_light_color[3];
float fog_sun_scatter;
float fog_aerial_perspective;
float time;
uint32_t pad[2];
}; };
static_assert(sizeof(UBO) % 16 == 0, "Scene UBO size must be a multiple of 16 bytes"); static_assert(sizeof(LightData) % 16 == 0, "LightData size must be a multiple of 16 bytes");
struct TonemapUBO { struct DirectionalLightData {
float exposure = 1.0; float direction[3];
float white = 1.0; float energy;
int32_t tonemapper = 0;
int32_t pad = 0; float color[3];
float size;
uint32_t enabled; // For use by SkyShaders
float pad[2];
float specular;
}; };
static_assert(sizeof(TonemapUBO) % 16 == 0, "Tonemap UBO size must be a multiple of 16 bytes"); static_assert(sizeof(DirectionalLightData) % 16 == 0, "DirectionalLightData size must be a multiple of 16 bytes");
UBO ubo; struct LightInstance {
GLuint ubo_buffer = 0; RS::LightType light_type = RS::LIGHT_DIRECTIONAL;
GLuint tonemap_buffer = 0;
bool used_depth_prepass = false; AABB aabb;
RID self;
RID light;
Transform3D transform;
GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX; Vector3 light_vector;
GLES3::SceneShaderData::DepthDraw current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE; Vector3 spot_vector;
GLES3::SceneShaderData::DepthTest current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_DISABLED; float linear_att = 0.0;
GLES3::SceneShaderData::Cull cull_mode = GLES3::SceneShaderData::CULL_BACK;
bool texscreen_copied = false; uint64_t shadow_pass = 0;
bool used_screen_texture = false; uint64_t last_scene_pass = 0;
bool used_normal_texture = false; uint64_t last_scene_shadow_pass = 0;
bool used_depth_texture = false; uint64_t last_pass = 0;
} scene_state; uint32_t cull_mask = 0;
uint32_t light_directional_index = 0;
Rect2 directional_rect;
uint32_t gl_id = -1;
LightInstance() {}
};
mutable RID_Owner<LightInstance> light_instance_owner;
struct GeometryInstanceGLES3; struct GeometryInstanceGLES3;
@ -295,9 +293,11 @@ private:
float parent_fade_alpha = 1.0; float parent_fade_alpha = 1.0;
uint32_t omni_light_count = 0; uint32_t omni_light_count = 0;
uint32_t omni_lights[8]; LocalVector<RID> omni_lights;
uint32_t spot_light_count = 0; uint32_t spot_light_count = 0;
uint32_t spot_lights[8]; LocalVector<RID> spot_lights;
LocalVector<uint32_t> omni_light_gl_cache;
LocalVector<uint32_t> spot_light_gl_cache;
//used during setup //used during setup
uint32_t base_flags = 0; uint32_t base_flags = 0;
@ -360,25 +360,96 @@ private:
void _geometry_instance_update(GeometryInstance *p_geometry_instance); void _geometry_instance_update(GeometryInstance *p_geometry_instance);
void _update_dirty_geometry_instances(); void _update_dirty_geometry_instances();
struct SceneState {
struct UBO {
float projection_matrix[16];
float inv_projection_matrix[16];
float inv_view_matrix[16];
float view_matrix[16];
float viewport_size[2];
float screen_pixel_size[2];
float ambient_light_color_energy[4];
float ambient_color_sky_mix;
uint32_t material_uv2_mode;
float pad2;
uint32_t use_ambient_light = 0;
uint32_t use_ambient_cubemap = 0;
uint32_t use_reflection_cubemap = 0;
float fog_aerial_perspective;
float time;
float radiance_inverse_xform[12];
uint32_t directional_light_count;
float z_far;
float z_near;
float pad1;
uint32_t fog_enabled;
float fog_density;
float fog_height;
float fog_height_density;
float fog_light_color[3];
float fog_sun_scatter;
};
static_assert(sizeof(UBO) % 16 == 0, "Scene UBO size must be a multiple of 16 bytes");
struct TonemapUBO {
float exposure = 1.0;
float white = 1.0;
int32_t tonemapper = 0;
int32_t pad = 0;
};
static_assert(sizeof(TonemapUBO) % 16 == 0, "Tonemap UBO size must be a multiple of 16 bytes");
UBO ubo;
GLuint ubo_buffer = 0;
GLuint tonemap_buffer = 0;
bool used_depth_prepass = false;
GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX;
GLES3::SceneShaderData::DepthDraw current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE;
GLES3::SceneShaderData::DepthTest current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_DISABLED;
GLES3::SceneShaderData::Cull cull_mode = GLES3::SceneShaderData::CULL_BACK;
bool texscreen_copied = false;
bool used_screen_texture = false;
bool used_normal_texture = false;
bool used_depth_texture = false;
LightData *omni_lights = nullptr;
LightData *spot_lights = nullptr;
InstanceSort<LightInstance> *omni_light_sort;
InstanceSort<LightInstance> *spot_light_sort;
GLuint omni_light_buffer = 0;
GLuint spot_light_buffer = 0;
uint32_t omni_light_count = 0;
uint32_t spot_light_count = 0;
DirectionalLightData *directional_lights = nullptr;
GLuint directional_light_buffer = 0;
} scene_state;
struct RenderListParameters { struct RenderListParameters {
GeometryInstanceSurface **elements = nullptr; GeometryInstanceSurface **elements = nullptr;
int element_count = 0; int element_count = 0;
bool reverse_cull = false; bool reverse_cull = false;
uint32_t spec_constant_base_flags = 0; uint32_t spec_constant_base_flags = 0;
bool force_wireframe = false; bool force_wireframe = false;
Plane lod_plane;
float lod_distance_multiplier = 0.0;
float screen_mesh_lod_threshold = 0.0;
RenderListParameters(GeometryInstanceSurface **p_elements, int p_element_count, bool p_reverse_cull, uint32_t p_spec_constant_base_flags, bool p_force_wireframe = false, const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0) { RenderListParameters(GeometryInstanceSurface **p_elements, int p_element_count, bool p_reverse_cull, uint32_t p_spec_constant_base_flags, bool p_force_wireframe = false) {
elements = p_elements; elements = p_elements;
element_count = p_element_count; element_count = p_element_count;
reverse_cull = p_reverse_cull; reverse_cull = p_reverse_cull;
spec_constant_base_flags = p_spec_constant_base_flags; spec_constant_base_flags = p_spec_constant_base_flags;
force_wireframe = p_force_wireframe; force_wireframe = p_force_wireframe;
lod_plane = p_lod_plane;
lod_distance_multiplier = p_lod_distance_multiplier;
screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
} }
}; };
@ -438,6 +509,7 @@ private:
RenderList render_list[RENDER_LIST_MAX]; RenderList render_list[RENDER_LIST_MAX];
void _setup_lights(const RenderDataGLES3 *p_render_data, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_omni_light_count, uint32_t &r_spot_light_count);
void _setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows); void _setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows);
void _fill_render_list(RenderListType p_render_list, const RenderDataGLES3 *p_render_data, PassMode p_pass_mode, bool p_append = false); void _fill_render_list(RenderListType p_render_list, const RenderDataGLES3 *p_render_data, PassMode p_pass_mode, bool p_append = false);
@ -637,6 +709,33 @@ protected:
/* Sky */ /* Sky */
struct SkyGlobals {
float fog_aerial_perspective = 0.0;
Color fog_light_color;
float fog_sun_scatter = 0.0;
bool fog_enabled = false;
float fog_density = 0.0;
float z_far = 0.0;
uint32_t directional_light_count = 0;
DirectionalLightData *directional_lights = nullptr;
DirectionalLightData *last_frame_directional_lights = nullptr;
uint32_t last_frame_directional_light_count = 0;
GLuint directional_light_buffer = 0;
RID shader_default_version;
RID default_material;
RID default_shader;
RID fog_material;
RID fog_shader;
GLuint screen_triangle = 0;
GLuint screen_triangle_array = 0;
GLuint radical_inverse_vdc_cache_tex = 0;
uint32_t max_directional_lights = 4;
uint32_t roughness_layers = 8;
uint32_t ggx_samples = 128;
} sky_globals;
struct Sky { struct Sky {
// Screen Buffers // Screen Buffers
GLuint half_res_pass = 0; GLuint half_res_pass = 0;
@ -648,11 +747,13 @@ protected:
// Radiance Cubemap // Radiance Cubemap
GLuint radiance = 0; GLuint radiance = 0;
GLuint radiance_framebuffer = 0; GLuint radiance_framebuffer = 0;
GLuint raw_radiance = 0;
RID material; RID material;
RID uniform_buffer; GLuint uniform_buffer;
int radiance_size = 256; int radiance_size = 256;
int mipmap_count = 1;
RS::SkyMode mode = RS::SKY_MODE_AUTOMATIC; RS::SkyMode mode = RS::SKY_MODE_AUTOMATIC;
@ -666,20 +767,18 @@ protected:
GLES3::SkyMaterialData *prev_material; GLES3::SkyMaterialData *prev_material;
Vector3 prev_position = Vector3(0.0, 0.0, 0.0); Vector3 prev_position = Vector3(0.0, 0.0, 0.0);
float prev_time = 0.0f; float prev_time = 0.0f;
void free();
bool set_radiance_size(int p_radiance_size);
bool set_mode(RS::SkyMode p_mode);
bool set_material(RID p_material);
Ref<Image> bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size);
}; };
Sky *dirty_sky_list = nullptr; Sky *dirty_sky_list = nullptr;
mutable RID_Owner<Sky, true> sky_owner; mutable RID_Owner<Sky, true> sky_owner;
void _setup_sky(Environment *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
void _invalidate_sky(Sky *p_sky); void _invalidate_sky(Sky *p_sky);
void _update_dirty_skys(); void _update_dirty_skys();
void _update_sky_radiance(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform);
void _filter_sky_radiance(Sky *p_sky, int p_base_layer);
void _draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform); void _draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform);
void _free_sky_data(Sky *p_sky);
public: public:
RasterizerStorageGLES3 *storage; RasterizerStorageGLES3 *storage;
@ -808,6 +907,15 @@ public:
void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override; void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
void light_instance_mark_visible(RID p_light_instance) override; void light_instance_mark_visible(RID p_light_instance) override;
_FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) {
LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->light_type;
}
_FORCE_INLINE_ uint32_t light_instance_get_gl_id(RID p_light_instance) {
LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
return li->gl_id;
}
RID fog_volume_instance_create(RID p_fog_volume) override; RID fog_volume_instance_create(RID p_fog_volume) override;
void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override; void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override;
void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override; void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override;

View file

@ -39,6 +39,19 @@
#include "servers/rendering/shader_language.h" #include "servers/rendering/shader_language.h"
void RasterizerStorageGLES3::base_update_dependency(RID p_base, DependencyTracker *p_instance) { void RasterizerStorageGLES3::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_base)) {
GLES3::Mesh *mesh = GLES3::MeshStorage::get_singleton()->get_mesh(p_base);
p_instance->update_dependency(&mesh->dependency);
} else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_base)) {
GLES3::MultiMesh *multimesh = GLES3::MeshStorage::get_singleton()->get_multimesh(p_base);
p_instance->update_dependency(&multimesh->dependency);
if (multimesh->mesh.is_valid()) {
base_update_dependency(multimesh->mesh, p_instance);
}
} else if (GLES3::LightStorage::get_singleton()->owns_light(p_base)) {
GLES3::Light *l = GLES3::LightStorage::get_singleton()->get_light(p_base);
p_instance->update_dependency(&l->dependency);
}
} }
/* VOXEL GI API */ /* VOXEL GI API */

View file

@ -219,7 +219,10 @@ protected:
Version *version = version_owner.get_or_null(p_version); Version *version = version_owner.get_or_null(p_version);
ERR_FAIL_COND_V(!version, -1); ERR_FAIL_COND_V(!version, -1);
ERR_FAIL_INDEX_V(p_variant, int(version->variants.size()), -1); ERR_FAIL_INDEX_V(p_variant, int(version->variants.size()), -1);
return version->variants[p_variant].lookup_ptr(p_specialization)->uniform_location[p_which]; Version::Specialization *spec = version->variants[p_variant].lookup_ptr(p_specialization);
ERR_FAIL_COND_V(!spec, -1);
ERR_FAIL_INDEX_V(p_which, int(spec->uniform_location.size()), -1);
return spec->uniform_location[p_which];
} }
virtual void _init() = 0; virtual void _init() = 0;

View file

@ -2,11 +2,18 @@
Import("env") Import("env")
env.Depends("#drivers/gles3/shaders/copy.glsl.gen.h", "#core/math/basis.h")
env.Depends("#drivers/gles3/shaders/copy.glsl.gen.h", "#core/math/transform_2d.h")
if "GLES3_GLSL" in env["BUILDERS"]: if "GLES3_GLSL" in env["BUILDERS"]:
# find all include files
gl_include_files = [str(f) for f in Glob("*_inc.glsl")]
# find all shader code(all glsl files excluding our include files)
glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
# make sure we recompile shaders if include files change
env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files)
env.GLES3_GLSL("canvas.glsl") env.GLES3_GLSL("canvas.glsl")
env.GLES3_GLSL("copy.glsl") env.GLES3_GLSL("copy.glsl")
env.GLES3_GLSL("scene.glsl") env.GLES3_GLSL("scene.glsl")
env.GLES3_GLSL("sky.glsl") env.GLES3_GLSL("sky.glsl")
env.GLES3_GLSL("cubemap_filter.glsl")

View file

@ -1,136 +1,102 @@
/* clang-format off */ /* clang-format off */
[vertex] #[modes]
#ifdef USE_GLES_OVER_GL mode_default =
#define lowp mode_copy = #define MODE_DIRECT_WRITE
#define mediump
#define highp
#else
precision highp float;
precision highp int;
#endif
layout(location = 0) in highp vec2 vertex; #[specializations]
#[vertex]
layout(location = 0) in highp vec2 vertex_attrib;
/* clang-format on */ /* clang-format on */
layout(location = 4) in highp vec2 uv;
out highp vec2 uv_interp; out highp vec2 uv_interp;
void main() { void main() {
uv_interp = uv; uv_interp = vertex_attrib;
gl_Position = vec4(vertex, 0, 1); gl_Position = vec4(uv_interp, 0.0, 1.0);
} }
/* clang-format off */ /* clang-format off */
[fragment] #[fragment]
#ifdef USE_GLES_OVER_GL
#define lowp
#define mediump
#define highp
#else
#if defined(USE_HIGHP_PRECISION)
precision highp float;
precision highp int;
#else
precision mediump float;
precision mediump int;
#endif
#endif #define M_PI 3.14159265359
#ifdef USE_SOURCE_PANORAMA
uniform sampler2D source_panorama; //texunit:0
#else
uniform samplerCube source_cube; //texunit:0 uniform samplerCube source_cube; //texunit:0
#endif
/* clang-format on */ /* clang-format on */
uniform int face_id; uniform int face_id;
uniform float roughness; uniform float roughness;
uniform float face_size;
uniform int sample_count;
//Todo, profile on low end hardware to see if fixed loop is faster
#ifdef USE_FIXED_SAMPLES
#define FIXED_SAMPLE_COUNT 32
#endif
in highp vec2 uv_interp; in highp vec2 uv_interp;
uniform sampler2D radical_inverse_vdc_cache; // texunit:1 uniform sampler2D radical_inverse_vdc_cache; // texunit:1
layout(location = 0) out vec4 frag_color;
#define M_PI 3.14159265359 #define M_PI 3.14159265359
#ifdef LOW_QUALITY // Don't include tonemap_inc.glsl because all we want is these functions, we don't want the uniforms
vec3 linear_to_srgb(vec3 color) {
#define SAMPLE_COUNT 64 return max(vec3(1.055) * pow(color, vec3(0.416666667)) - vec3(0.055), vec3(0.0));
#else
#define SAMPLE_COUNT 512
#endif
#ifdef USE_SOURCE_PANORAMA
vec4 texturePanorama(sampler2D pano, vec3 normal) {
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 vec3 srgb_to_linear(vec3 color) {
return color * (color * (color * 0.305306011 + 0.682171111) + 0.012522878);
}
vec3 texelCoordToVec(vec2 uv, int faceID) { vec3 texelCoordToVec(vec2 uv, int faceID) {
mat3 faceUvVectors[6]; mat3 faceUvVectors[6];
// -x // -x
faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
// +x // +x
faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face
// -y // -y
faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
// +y // +y
faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z
faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face
// -z // -z
faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
// +z // +z
faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
// out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2]. // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
vec3 result; vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
for (int i = 0; i < 6; i++) {
if (i == faceID) {
result = (faceUvVectors[i][0] * uv.x) + (faceUvVectors[i][1] * uv.y) + faceUvVectors[i][2];
break;
}
}
return normalize(result); return normalize(result);
} }
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) { vec3 ImportanceSampleGGX(vec2 xi, float roughness4) {
float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
// Compute distribution direction // Compute distribution direction
float Phi = 2.0 * M_PI * Xi.x; float Phi = 2.0 * M_PI * xi.x;
float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y)); float CosTheta = sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y));
float SinTheta = sqrt(1.0 - CosTheta * CosTheta); float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
// Convert to spherical direction // Convert to spherical direction
@ -139,12 +105,26 @@ vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
H.y = SinTheta * sin(Phi); H.y = SinTheta * sin(Phi);
H.z = CosTheta; H.z = CosTheta;
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); return H;
vec3 TangentX = normalize(cross(UpVector, N)); }
vec3 TangentY = cross(N, TangentX);
// Tangent to world space float DistributionGGX(float NdotH, float roughness4) {
return TangentX * H.x + TangentY * H.y + N * H.z; float NdotH2 = NdotH * NdotH;
float denom = (NdotH2 * (roughness4 - 1.0) + 1.0);
denom = M_PI * denom * denom;
return roughness4 / denom;
}
// https://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);
}
// https://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 radical_inverse_VdC(int i) { float radical_inverse_VdC(int i) {
@ -155,60 +135,54 @@ vec2 Hammersley(int i, int N) {
return vec2(float(i) / float(N), radical_inverse_VdC(i)); return vec2(float(i) / float(N), radical_inverse_VdC(i));
} }
uniform bool z_flip;
layout(location = 0) out vec4 frag_color;
void main() { void main() {
vec3 color = vec3(0.0); vec3 color = vec3(0.0);
vec2 uv = uv_interp;
vec2 uv = (uv_interp * 2.0) - 1.0;
vec3 N = texelCoordToVec(uv, face_id); vec3 N = texelCoordToVec(uv, face_id);
#ifdef USE_DIRECT_WRITE #ifdef MODE_DIRECT_WRITE
frag_color = vec4(textureCubeLod(source_cube, N, 0.0).rgb, 1.0);
#ifdef USE_SOURCE_PANORAMA
frag_color = vec4(texturePanorama(source_panorama, N).rgb, 1.0);
#else
frag_color = vec4(textureCube(source_cube, N).rgb, 1.0);
#endif //USE_SOURCE_PANORAMA
#else #else
vec4 sum = vec4(0.0); vec4 sum = vec4(0.0);
float solid_angle_texel = 4.0 * M_PI / (6.0 * face_size * face_size);
float roughness2 = roughness * roughness;
float roughness4 = roughness2 * roughness2;
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
mat3 T;
T[0] = normalize(cross(UpVector, N));
T[1] = cross(N, T[0]);
T[2] = N;
for (int sample_num = 0; sample_num < SAMPLE_COUNT; sample_num++) { for (int sample_num = 0; sample_num < sample_count; sample_num++) {
vec2 xi = Hammersley(sample_num, SAMPLE_COUNT); vec2 xi = Hammersley(sample_num, sample_count);
vec3 H = ImportanceSampleGGX(xi, roughness, N); vec3 H = T * ImportanceSampleGGX(xi, roughness4);
vec3 V = N; float NdotH = dot(N, H);
vec3 L = (2.0 * dot(V, H) * H - V); vec3 L = (2.0 * NdotH * H - N);
float NdotL = clamp(dot(N, L), 0.0, 1.0); float NdotL = clamp(dot(N, L), 0.0, 1.0);
if (NdotL > 0.0) { if (NdotL > 0.0) {
float D = DistributionGGX(NdotH, roughness4);
float pdf = D * NdotH / (4.0 * NdotH) + 0.0001;
#ifdef USE_SOURCE_PANORAMA float solid_angle_sample = 1.0 / (float(sample_count) * pdf + 0.0001);
vec3 val = texturePanorama(source_panorama, L).rgb;
#else float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(solid_angle_sample / solid_angle_texel);
vec3 val = textureCubeLod(source_cube, L, 0.0).rgb;
#endif vec3 val = textureCubeLod(source_cube, L, mipLevel).rgb;
//mix using Linear, to approximate high end back-end // Mix using linear
val = mix(pow((val + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), val * (1.0 / 12.92), vec3(lessThan(val, vec3(0.04045)))); val = srgb_to_linear(val);
sum.rgb += val * NdotL; sum.rgb += val * NdotL;
sum.a += NdotL; sum.a += NdotL;
} }
} }
sum /= sum.a; sum /= sum.a;
vec3 a = vec3(0.055); sum.rgb = linear_to_srgb(sum.rgb);
sum.rgb = mix((vec3(1.0) + a) * pow(sum.rgb, vec3(1.0 / 2.4)) - a, 12.92 * sum.rgb, vec3(lessThan(sum.rgb, vec3(0.0031308))));
frag_color = vec4(sum.rgb, 1.0); frag_color = vec4(sum.rgb, 1.0);
#endif #endif
} }

View file

@ -7,9 +7,12 @@ mode_depth = #define MODE_RENDER_DEPTH
#[specializations] #[specializations]
USE_LIGHTMAP = false DISABLE_LIGHTMAP = false
USE_LIGHT_DIRECTIONAL = false DISABLE_LIGHT_DIRECTIONAL = false
USE_LIGHT_POSITIONAL = false DISABLE_LIGHT_OMNI = false
DISABLE_LIGHT_SPOT = false
DISABLE_FOG = false
USE_RADIANCE_MAP = true
#[vertex] #[vertex]
@ -109,12 +112,14 @@ layout(std140) uniform SceneData { // ubo:2
mediump vec4 ambient_light_color_energy; mediump vec4 ambient_light_color_energy;
mediump float ambient_color_sky_mix; mediump float ambient_color_sky_mix;
uint ambient_flags;
bool material_uv2_mode; bool material_uv2_mode;
float opaque_prepass_threshold; float pad2;
//bool use_ambient_light; bool use_ambient_light;
//bool use_ambient_cubemap; bool use_ambient_cubemap;
//bool use_reflection_cubemap; bool use_reflection_cubemap;
float fog_aerial_perspective;
float time;
mat3 radiance_inverse_xform; mat3 radiance_inverse_xform;
@ -130,13 +135,6 @@ layout(std140) uniform SceneData { // ubo:2
vec3 fog_light_color; vec3 fog_light_color;
float fog_sun_scatter; float fog_sun_scatter;
float fog_aerial_perspective;
float time;
float reflection_multiplier; // one normally, zero when rendering reflections
bool pancake_shadows;
} }
scene_data; scene_data;
@ -169,7 +167,7 @@ out vec2 uv2_interp;
#endif #endif
#endif #endif
#if defined(TANGENT_USED) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
out vec3 tangent_interp; out vec3 tangent_interp;
out vec3 binormal_interp; out vec3 binormal_interp;
#endif #endif
@ -191,9 +189,6 @@ layout(std140) uniform MaterialUniforms { // ubo:3
#GLOBALS #GLOBALS
/* clang-format on */ /* clang-format on */
out highp vec4 position_interp;
invariant gl_Position; invariant gl_Position;
void main() { void main() {
@ -206,21 +201,16 @@ void main() {
#endif #endif
highp mat3 model_normal_matrix = mat3(model_matrix); highp mat3 model_normal_matrix = mat3(model_matrix);
#if defined(TANGENT_USED) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
vec3 tangent; vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
float binormalf; float binormalf = tangent_attrib.a * 2.0 - 1.0;
tangent = normal_tangent_attrib.xyz; vec3 binormal = normalize(cross(normal, tangent) * binormalf);
binormalf = normal_tangent_attrib.a;
#endif #endif
#if defined(COLOR_USED) #if defined(COLOR_USED)
color_interp = color_attrib; color_interp = color_attrib;
#endif #endif
#if defined(TANGENT_USED) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
#if defined(UV_USED) #if defined(UV_USED)
uv_interp = uv_attrib; uv_interp = uv_attrib;
#endif #endif
@ -306,7 +296,7 @@ void main() {
normal_interp = normal; normal_interp = normal;
#endif #endif
#if defined(TANGENT_USED) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
tangent_interp = tangent; tangent_interp = tangent;
binormal_interp = binormal; binormal_interp = binormal;
#endif #endif
@ -316,16 +306,6 @@ void main() {
#else #else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0); gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif #endif
#ifdef MODE_RENDER_DEPTH
if (scene_data.pancake_shadows) {
if (gl_Position.z <= 0.00001) {
gl_Position.z = 0.00001;
}
}
#endif
position_interp = gl_Position;
} }
/* clang-format off */ /* clang-format off */
@ -357,10 +337,9 @@ void main() {
*/ */
uniform highp mat4 world_transform; #define M_PI 3.14159265359
/* clang-format on */ /* clang-format on */
#define M_PI 3.14159265359
#define SHADER_IS_SRGB true #define SHADER_IS_SRGB true
/* Varyings */ /* Varyings */
@ -381,7 +360,7 @@ in vec2 uv2_interp;
#endif #endif
#endif #endif
#if defined(TANGENT_USED) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
in vec3 tangent_interp; in vec3 tangent_interp;
in vec3 binormal_interp; in vec3 binormal_interp;
#endif #endif
@ -392,29 +371,11 @@ in vec3 normal_interp;
in highp vec3 vertex_interp; in highp vec3 vertex_interp;
/* PBR CHANNELS */
#ifdef USE_RADIANCE_MAP #ifdef USE_RADIANCE_MAP
layout(std140) uniform Radiance { // ubo:4
mat4 radiance_inverse_xform;
float radiance_ambient_contribution;
};
#define RADIANCE_MAX_LOD 5.0 #define RADIANCE_MAX_LOD 5.0
uniform sampler2D radiance_map; // texunit:-2 uniform samplerCube radiance_map; // texunit:-2
vec3 textureDualParaboloid(sampler2D p_tex, vec3 p_vec, float p_roughness) {
vec3 norm = normalize(p_vec);
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(p_tex, norm.xy, p_roughness * RADIANCE_MAX_LOD).xyz;
}
#endif #endif
@ -448,12 +409,14 @@ layout(std140) uniform SceneData { // ubo:2
mediump vec4 ambient_light_color_energy; mediump vec4 ambient_light_color_energy;
mediump float ambient_color_sky_mix; mediump float ambient_color_sky_mix;
uint ambient_flags;
bool material_uv2_mode; bool material_uv2_mode;
float opaque_prepass_threshold; float pad2;
//bool use_ambient_light; bool use_ambient_light;
//bool use_ambient_cubemap; bool use_ambient_cubemap;
//bool use_reflection_cubemap; bool use_reflection_cubemap;
float fog_aerial_perspective;
float time;
mat3 radiance_inverse_xform; mat3 radiance_inverse_xform;
@ -469,13 +432,6 @@ layout(std140) uniform SceneData { // ubo:2
vec3 fog_light_color; vec3 fog_light_color;
float fog_sun_scatter; float fog_sun_scatter;
float fog_aerial_perspective;
float time;
float reflection_multiplier; // one normally, zero when rendering reflections
bool pancake_shadows;
} }
scene_data; scene_data;
@ -487,7 +443,7 @@ scene_data;
//directional light data //directional light data
#ifdef USE_LIGHT_DIRECTIONAL #ifndef DISABLE_LIGHT_DIRECTIONAL
struct DirectionalLightData { struct DirectionalLightData {
mediump vec3 direction; mediump vec3 direction;
@ -498,10 +454,14 @@ struct DirectionalLightData {
mediump float specular; mediump float specular;
}; };
layout(std140) uniform DirectionalLights { // ubo:7
DirectionalLightData directional_lights[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
};
#endif #endif
// omni and spot // omni and spot
#ifdef USE_LIGHT_POSITIONAL #if !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT)
struct LightData { //this structure needs to be as packed as possible struct LightData { //this structure needs to be as packed as possible
highp vec3 position; highp vec3 position;
highp float inv_radius; highp float inv_radius;
@ -517,36 +477,38 @@ struct LightData { //this structure needs to be as packed as possible
mediump float specular_amount; mediump float specular_amount;
bool shadow_enabled; bool shadow_enabled;
}; };
#ifndef DISABLE_LIGHT_OMNI
layout(std140) uniform OmniLightData { // ubo:5 layout(std140) uniform OmniLightData { // ubo:5
LightData omni_lights[MAX_LIGHT_DATA_STRUCTS]; LightData omni_lights[MAX_LIGHT_DATA_STRUCTS];
}; };
uniform uint omni_light_indices[MAX_FORWARD_LIGHTS];
uniform int omni_light_count;
#endif
#ifndef DISABLE_LIGHT_SPOT
layout(std140) uniform SpotLightData { // ubo:6 layout(std140) uniform SpotLightData { // ubo:6
LightData spot_lights[MAX_LIGHT_DATA_STRUCTS]; LightData spot_lights[MAX_LIGHT_DATA_STRUCTS];
}; };
uniform uint spot_light_indices[MAX_FORWARD_LIGHTS];
uniform highp samplerCubeShadow positional_shadow; // texunit:-6
uniform int omni_light_indices[MAX_FORWARD_LIGHTS];
uniform int omni_light_count;
uniform int spot_light_indices[MAX_FORWARD_LIGHTS];
uniform int spot_light_count; uniform int spot_light_count;
uniform int reflection_indices[MAX_FORWARD_LIGHTS];
uniform int reflection_count;
#endif #endif
#ifdef USE_ADDITIVE_LIGHTING
uniform highp samplerCubeShadow positional_shadow; // texunit:-4
#endif
#endif // !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT)
uniform highp sampler2D screen_texture; // texunit:-5 uniform highp sampler2D screen_texture; // texunit:-5
uniform highp sampler2D depth_buffer; // texunit:-6 uniform highp sampler2D depth_buffer; // texunit:-6
layout(location = 0) out vec4 frag_color; uniform highp mat4 world_transform;
uniform mediump float opaque_prepass_threshold;
in highp vec4 position_interp; layout(location = 0) out vec4 frag_color;
vec3 F0(float metallic, float specular, vec3 albedo) { vec3 F0(float metallic, float specular, vec3 albedo) {
float dielectric = 0.16 * specular * specular; float dielectric = 0.16 * specular * specular;
@ -555,7 +517,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, vec3(metallic)); return mix(vec3(dielectric), albedo, vec3(metallic));
} }
#if defined(USE_LIGHT_DIRECTIONAL) || defined(USE_LIGHT_POSITIONAL) #if !defined(DISABLE_LIGHT_DIRECTIONAL) || !defined(DISABLE_LIGHT_OMNI) || !defined(DISABLE_LIGHT_SPOT)
float D_GGX(float cos_theta_m, float alpha) { float D_GGX(float cos_theta_m, float alpha) {
float a = cos_theta_m * alpha; float a = cos_theta_m * alpha;
float k = alpha / (1.0 - cos_theta_m * cos_theta_m + a * a); float k = alpha / (1.0 - cos_theta_m * cos_theta_m + a * a);
@ -588,7 +550,7 @@ float SchlickFresnel(float u) {
return m2 * m2 * m; // pow(m,5) return m2 * m2 * m; // pow(m,5)
} }
void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha, void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, float roughness, float metallic, float specular_amount, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED #ifdef LIGHT_BACKLIGHT_USED
vec3 backlight, vec3 backlight,
#endif #endif
@ -603,11 +565,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#endif #endif
inout vec3 diffuse_light, inout vec3 specular_light) { inout vec3 diffuse_light, inout vec3 specular_light) {
vec4 orms_unpacked = unpackUnorm4x8(orms);
float roughness = orms_unpacked.y;
float metallic = orms_unpacked.z;
#if defined(USE_LIGHT_SHADER_CODE) #if defined(USE_LIGHT_SHADER_CODE)
// light is written by the light shader // light is written by the light shader
@ -626,7 +583,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float NdotL = min(A + dot(N, L), 1.0); float NdotL = min(A + dot(N, L), 1.0);
float cNdotL = max(NdotL, 0.0); // clamped NdotL float cNdotL = max(NdotL, 0.0); // clamped NdotL
float NdotV = dot(N, V); float NdotV = dot(N, V);
float cNdotV = max(NdotV, 0.0); float cNdotV = max(NdotV, 1e-4);
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) #if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
vec3 H = normalize(V + L); vec3 H = normalize(V + L);
@ -752,15 +709,10 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
return nd * pow(max(distance, 0.0001), -decay); return nd * pow(max(distance, 0.0001), -decay);
} }
void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha, void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED #ifdef LIGHT_BACKLIGHT_USED
vec3 backlight, vec3 backlight,
#endif #endif
#ifdef LIGHT_TRANSMITTANCE_USED
vec4 transmittance_color,
float transmittance_depth,
float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED #ifdef LIGHT_RIM_USED
float rim, float rim_tint, float rim, float rim_tint,
#endif #endif
@ -774,16 +726,15 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
vec3 light_rel_vec = omni_lights[idx].position - vertex; vec3 light_rel_vec = omni_lights[idx].position - vertex;
float light_length = length(light_rel_vec); float light_length = length(light_rel_vec);
float omni_attenuation = get_omni_attenuation(light_length, omni_lights[idx].inv_radius, omni_lights[idx].attenuation); float omni_attenuation = get_omni_attenuation(light_length, omni_lights[idx].inv_radius, omni_lights[idx].attenuation);
vec3 light_attenuation = vec3(omni_attenuation);
vec3 color = omni_lights[idx].color; vec3 color = omni_lights[idx].color;
float size_A = 0.0; float size_A = 0.0;
if (omni_lights.data[idx].size > 0.0) { if (omni_lights[idx].size > 0.0) {
float t = omni_lights[idx].size / max(0.001, light_length); float t = omni_lights[idx].size / max(0.001, light_length);
size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
} }
light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights[idx].specular_amount, albedo, alpha, light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, omni_attenuation, f0, roughness, metallic, omni_lights[idx].specular_amount, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED #ifdef LIGHT_BACKLIGHT_USED
backlight, backlight,
#endif #endif
@ -800,7 +751,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
specular_light); specular_light);
} }
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha, void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED #ifdef LIGHT_BACKLIGHT_USED
vec3 backlight, vec3 backlight,
#endif #endif
@ -823,17 +774,16 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights[idx].cone_angle); float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights[idx].cone_angle);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights[idx].cone_angle)); float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights[idx].cone_angle));
spot_attenuation *= 1.0 - pow(spot_rim, spot_lights[idx].cone_attenuation); spot_attenuation *= 1.0 - pow(spot_rim, spot_lights[idx].cone_attenuation);
float light_attenuation = spot_attenuation;
vec3 color = spot_lights[idx].color; vec3 color = spot_lights[idx].color;
float size_A = 0.0; float size_A = 0.0;
if (spot_lights.data[idx].size > 0.0) { if (spot_lights[idx].size > 0.0) {
float t = spot_lights.data[idx].size / max(0.001, light_length); float t = spot_lights[idx].size / max(0.001, light_length);
size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
} }
light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights[idx].specular_amount, albedo, alpha, light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, spot_attenuation, f0, roughness, metallic, spot_lights[idx].specular_amount, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED #ifdef LIGHT_BACKLIGHT_USED
backlight, backlight,
#endif #endif
@ -848,7 +798,56 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
#endif #endif
diffuse_light, specular_light); diffuse_light, specular_light);
} }
#endif // defined(USE_LIGHT_DIRECTIONAL) || defined(USE_LIGHT_POSITIONAL) #endif // !defined(DISABLE_LIGHT_DIRECTIONAL) || !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT)
#ifndef MODE_RENDER_DEPTH
vec4 fog_process(vec3 vertex) {
vec3 fog_color = scene_data.fog_light_color;
#ifdef USE_RADIANCE_MAP
/*
if (scene_data.fog_aerial_perspective > 0.0) {
vec3 sky_fog_color = vec3(0.0);
vec3 cube_view = scene_data.radiance_inverse_xform * vertex;
// mip_level always reads from the second mipmap and higher so the fog is always slightly blurred
float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near));
sky_fog_color = textureCubeLod(radiance_map, cube_view, mip_level * RADIANCE_MAX_LOD).rgb;
fog_color = mix(fog_color, sky_fog_color, scene_data.fog_aerial_perspective);
}
*/
#endif
#ifndef DISABLE_LIGHT_DIRECTIONAL
if (scene_data.fog_sun_scatter > 0.001) {
vec4 sun_scatter = vec4(0.0);
float sun_total = 0.0;
vec3 view = normalize(vertex);
for (uint i = uint(0); i < scene_data.directional_light_count; i++) {
vec3 light_color = directional_lights[i].color * directional_lights[i].energy;
float light_amount = pow(max(dot(view, directional_lights[i].direction), 0.0), 8.0);
fog_color += light_color * light_amount * scene_data.fog_sun_scatter;
}
}
#endif // !DISABLE_LIGHT_DIRECTIONAL
float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
if (abs(scene_data.fog_height_density) >= 0.0001) {
float y = (scene_data.inv_view_matrix * vec4(vertex, 1.0)).y;
float y_dist = y - scene_data.fog_height;
float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density));
fog_amount = max(vfog_amount, fog_amount);
}
return vec4(fog_color, fog_amount);
}
#endif // !MODE_RENDER_DEPTH
void main() { void main() {
//lay out everything, whatever is unused is optimized away anyway //lay out everything, whatever is unused is optimized away anyway
@ -951,7 +950,7 @@ void main() {
#ifdef USE_OPAQUE_PREPASS #ifdef USE_OPAQUE_PREPASS
#if !defined(ALPHA_SCISSOR_USED) #if !defined(ALPHA_SCISSOR_USED)
if (alpha < scene_data.opaque_prepass_threshold) { if (alpha < opaque_prepass_threshold) {
discard; discard;
} }
@ -982,9 +981,31 @@ void main() {
#endif #endif
#ifndef MODE_RENDER_DEPTH #ifndef MODE_RENDER_DEPTH
#ifndef CUSTOM_FOG_USED
#ifndef DISABLE_FOG
// fog must be processed as early as possible and then packed.
// to maximize VGPR usage
if (scene_data.fog_enabled) {
fog = fog_process(vertex);
}
#endif // !DISABLE_FOG
#endif //!CUSTOM_FOG_USED
uint fog_rg = packHalf2x16(fog.rg);
uint fog_ba = packHalf2x16(fog.ba);
#endif //!MODE_RENDER_DEPTH
#ifndef MODE_RENDER_DEPTH
// Convert colors to linear
albedo = srgb_to_linear(albedo);
emission = srgb_to_linear(emission);
// TODO Backlight and transmittance when used
#ifndef MODE_UNSHADED
vec3 f0 = F0(metallic, specular, albedo); vec3 f0 = F0(metallic, specular, albedo);
// Convert albedo to linear. Approximation from: http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
albedo = albedo * (albedo * (albedo * 0.305306011 + 0.682171111) + 0.012522878);
vec3 specular_light = vec3(0.0, 0.0, 0.0); vec3 specular_light = vec3(0.0, 0.0, 0.0);
vec3 diffuse_light = vec3(0.0, 0.0, 0.0); vec3 diffuse_light = vec3(0.0, 0.0, 0.0);
vec3 ambient_light = vec3(0.0, 0.0, 0.0); vec3 ambient_light = vec3(0.0, 0.0, 0.0);
@ -996,15 +1017,58 @@ void main() {
float ndotv = clamp(dot(normal, view), 0.0, 1.0); float ndotv = clamp(dot(normal, view), 0.0, 1.0);
vec3 F = f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - ndotv, 5.0); vec3 F = f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - ndotv, 5.0);
// Calculate IBL #ifdef USE_RADIANCE_MAP
// Calculate Reflection probes if (scene_data.use_reflection_cubemap) {
// Caclculate Lightmaps #ifdef LIGHT_ANISOTROPY_USED
// https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
float specular_blob_intensity = 1.0; vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
vec3 anisotropic_tangent = cross(anisotropic_direction, view);
#if defined(SPECULAR_TOON) vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
specular_blob_intensity *= specular * 2.0; vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
vec3 ref_vec = reflect(-view, bent_normal);
#else
vec3 ref_vec = reflect(-view, normal);
#endif #endif
float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).rgb;
specular_light = srgb_to_linear(specular_light);
specular_light *= horizon * horizon;
specular_light *= scene_data.ambient_light_color_energy.a;
}
#endif
// Calculate Reflection probes
// Calculate Lightmaps
#if defined(CUSTOM_RADIANCE_USED)
specular_light = mix(specular_light, custom_radiance.rgb, custom_radiance.a);
#endif // CUSTOM_RADIANCE_USED
#ifndef USE_LIGHTMAP
//lightmap overrides everything
if (scene_data.use_ambient_light) {
ambient_light = scene_data.ambient_light_color_energy.rgb;
#ifdef USE_RADIANCE_MAP
if (scene_data.use_ambient_cubemap) {
vec3 ambient_dir = scene_data.radiance_inverse_xform * normal;
vec3 cubemap_ambient = textureCubeLod(radiance_map, ambient_dir, RADIANCE_MAX_LOD).rgb;
cubemap_ambient = srgb_to_linear(cubemap_ambient);
ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix);
}
#endif
}
#endif // USE_LIGHTMAP
#if defined(CUSTOM_IRRADIANCE_USED)
ambient_light = mix(ambient_light, custom_irradiance.rgb, custom_irradiance.a);
#endif // CUSTOM_IRRADIANCE_USED
ambient_light *= albedo.rgb;
ambient_light *= ao;
// convert ao to direct light ao
ao = mix(1.0, ao, ao_light_affect);
{ {
#if defined(DIFFUSE_TOON) #if defined(DIFFUSE_TOON)
@ -1029,14 +1093,10 @@ void main() {
#endif // BASE_PASS #endif // BASE_PASS
//this saves some VGPRs #ifndef DISABLE_LIGHT_DIRECTIONAL
uint orms = packUnorm4x8(vec4(ao, roughness, metallic, specular)); //diffuse_light = normal; //
for (uint i = uint(0); i < scene_data.directional_light_count; i++) {
#ifdef USE_LIGHT_DIRECTIONAL light_compute(normal, normalize(directional_lights[i].direction), normalize(view), directional_lights[i].size, directional_lights[i].color * directional_lights[i].energy, 1.0, f0, roughness, metallic, 1.0, albedo, alpha,
float size_A = directional_lights[i].size;
light_compute(normal, directional_lights[i].direction, normalize(view), size_A, directional_lights[i].color * directional_lights[i].energy, shadow, f0, orms, 1.0, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED #ifdef LIGHT_BACKLIGHT_USED
backlight, backlight,
#endif #endif
@ -1052,13 +1112,15 @@ void main() {
#endif #endif
diffuse_light, diffuse_light,
specular_light); specular_light);
}
#endif //!DISABLE_LIGHT_DIRECTIONAL
#endif //#USE_LIGHT_DIRECTIONAL #ifndef DISABLE_LIGHT_OMNI
for (int i = 0; i < MAX_FORWARD_LIGHTS; i++) {
#ifdef USE_LIGHT_POSITIONAL if (i >= omni_light_count) {
float shadow = 0.0; break;
for (int i = 0; i < omni_light_count; i++) { }
light_process_omni(omni_light_indices[i], vertex, view, normal, f0, orms, shadow, albedo, alpha, light_process_omni(omni_light_indices[i], vertex, view, normal, f0, roughness, metallic, 0.0, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED #ifdef LIGHT_BACKLIGHT_USED
backlight, backlight,
#endif #endif
@ -1070,13 +1132,18 @@ void main() {
clearcoat, clearcoat_roughness, normalize(normal_interp), clearcoat, clearcoat_roughness, normalize(normal_interp),
#endif #endif
#ifdef LIGHT_ANISOTROPY_USED #ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy, binormal, tangent, anisotropy,
#endif #endif
diffuse_light, specular_light); diffuse_light, specular_light);
} }
#endif // !DISABLE_LIGHT_OMNI
for (int i = 0; i < spot_light_count; i++) { #ifndef DISABLE_LIGHT_SPOT
light_process_spot(spot_light_indices[i], vertex, view, normal, f0, orms, shadow, albedo, alpha, for (int i = 0; i < MAX_FORWARD_LIGHTS; i++) {
if (i >= spot_light_count) {
break;
}
light_process_spot(spot_light_indices[i], vertex, view, normal, f0, roughness, metallic, 0.0, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED #ifdef LIGHT_BACKLIGHT_USED
backlight, backlight,
#endif #endif
@ -1094,8 +1161,9 @@ void main() {
diffuse_light, specular_light); diffuse_light, specular_light);
} }
#endif // USE_LIGHT_POSITIONAL #endif // !DISABLE_LIGHT_SPOT
#endif //!MODE_RENDER_DEPTH #endif // !MODE_UNSHADED
#endif // !MODE_RENDER_DEPTH
#if defined(USE_SHADOW_TO_OPACITY) #if defined(USE_SHADOW_TO_OPACITY)
alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0)); alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
@ -1122,21 +1190,31 @@ void main() {
//nothing happens, so a tree-ssa optimizer will result in no fragment shader :) //nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
#else // !MODE_RENDER_DEPTH #else // !MODE_RENDER_DEPTH
specular_light *= scene_data.reflection_multiplier;
ambient_light *= albedo; //ambient must be multiplied by albedo at the end
// base color remapping
diffuse_light *= 1.0 - metallic;
ambient_light *= 1.0 - metallic;
#ifdef MODE_UNSHADED #ifdef MODE_UNSHADED
frag_color = vec4(albedo, alpha); frag_color = vec4(albedo, alpha);
#else #else
frag_color = vec4(ambient_light + diffuse_light + specular_light, alpha);
diffuse_light *= albedo;
diffuse_light *= 1.0 - metallic;
ambient_light *= 1.0 - metallic;
frag_color = vec4(diffuse_light + specular_light, alpha);
#ifdef BASE_PASS #ifdef BASE_PASS
frag_color.rgb += emission; frag_color.rgb += emission + ambient_light;
#endif #endif
#endif //MODE_UNSHADED #endif //MODE_UNSHADED
fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba));
#ifndef DISABLE_FOG
if (scene_data.fog_enabled) {
#ifdef BASE_PASS
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
#else
frag_color.rgb *= (1.0 - fog.a);
#endif // BASE_PASS
}
#endif
// Tonemap before writing as we are writing to an sRGB framebuffer // Tonemap before writing as we are writing to an sRGB framebuffer
frag_color.rgb *= exposure; frag_color.rgb *= exposure;

View file

@ -12,13 +12,13 @@ mode_cubemap_quarter_res = #define USE_CUBEMAP_PASS \n#define USE_QUARTER_RES_PA
#[vertex] #[vertex]
layout(location = 0) in vec2 vertex_attrib;
out vec2 uv_interp; out vec2 uv_interp;
/* clang-format on */ /* clang-format on */
void main() { void main() {
// One big triangle to cover the whole screen uv_interp = vertex_attrib;
vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(3.0, -1.0), vec2(-1.0, 3.0));
uv_interp = base_arr[gl_VertexID];
gl_Position = vec4(uv_interp, 1.0, 1.0); gl_Position = vec4(uv_interp, 1.0, 1.0);
} }
@ -46,18 +46,13 @@ layout(std140) uniform GlobalVariableData { //ubo:1
vec4 global_variables[MAX_GLOBAL_VARIABLES]; vec4 global_variables[MAX_GLOBAL_VARIABLES];
}; };
layout(std140) uniform SceneData { //ubo:2
float pad1;
float pad2;
};
struct DirectionalLightData { struct DirectionalLightData {
vec4 direction_energy; vec4 direction_energy;
vec4 color_size; vec4 color_size;
bool enabled; bool enabled;
}; };
layout(std140) uniform DirectionalLights { //ubo:3 layout(std140) uniform DirectionalLights { //ubo:4
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS]; DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
} }
directional_lights; directional_lights;
@ -65,7 +60,7 @@ directional_lights;
/* clang-format off */ /* clang-format off */
#ifdef MATERIAL_UNIFORMS_USED #ifdef MATERIAL_UNIFORMS_USED
layout(std140) uniform MaterialUniforms{ //ubo:4 layout(std140) uniform MaterialUniforms{ //ubo:3
#MATERIAL_UNIFORMS #MATERIAL_UNIFORMS
@ -98,6 +93,14 @@ uniform vec4 projection;
uniform vec3 position; uniform vec3 position;
uniform float time; uniform float time;
uniform float fog_aerial_perspective;
uniform vec3 fog_light_color;
uniform float fog_sun_scatter;
uniform bool fog_enabled;
uniform float fog_density;
uniform float z_far;
uniform uint directional_light_count;
layout(location = 0) out vec4 frag_color; layout(location = 0) out vec4 frag_color;
void main() { void main() {
@ -106,12 +109,11 @@ void main() {
cube_normal.x = (uv_interp.x + projection.x) / projection.y; cube_normal.x = (uv_interp.x + projection.x) / projection.y;
cube_normal.y = (-uv_interp.y - projection.z) / projection.w; cube_normal.y = (-uv_interp.y - projection.z) / projection.w;
cube_normal = mat3(orientation) * cube_normal; cube_normal = mat3(orientation) * cube_normal;
cube_normal.z = -cube_normal.z;
cube_normal = normalize(cube_normal); cube_normal = normalize(cube_normal);
vec2 uv = gl_FragCoord.xy; // uv_interp * 0.5 + 0.5; vec2 uv = gl_FragCoord.xy; // uv_interp * 0.5 + 0.5;
vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y)); vec2 panorama_coords = vec2(atan(cube_normal.x, -cube_normal.z), acos(cube_normal.y));
if (panorama_coords.x < 0.0) { if (panorama_coords.x < 0.0) {
panorama_coords.x += M_PI * 2.0; panorama_coords.x += M_PI * 2.0;
@ -126,13 +128,11 @@ void main() {
vec4 custom_fog = vec4(0.0); vec4 custom_fog = vec4(0.0);
#ifdef USE_CUBEMAP_PASS #ifdef USE_CUBEMAP_PASS
vec3 inverted_cube_normal = cube_normal;
inverted_cube_normal.z *= -1.0;
#ifdef USES_HALF_RES_COLOR #ifdef USES_HALF_RES_COLOR
half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal); half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal);
#endif #endif
#ifdef USES_QUARTER_RES_COLOR #ifdef USES_QUARTER_RES_COLOR
quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal); quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal);
#endif #endif
#else #else
#ifdef USES_HALF_RES_COLOR #ifdef USES_HALF_RES_COLOR
@ -149,7 +149,8 @@ void main() {
} }
// Tonemap before writing as we are writing to an sRGB framebuffer // Convert to Linear for tonemapping so color matches scene shader better
color = srgb_to_linear(color);
color *= exposure; color *= exposure;
color = apply_tonemapping(color, white); color = apply_tonemapping(color, white);
color = linear_to_srgb(color); color = linear_to_srgb(color);

View file

@ -42,11 +42,11 @@ vec2 unpackSnorm2x16(uint p) {
uint packUnorm4x8(vec4 v) { uint packUnorm4x8(vec4 v) {
uvec4 uv = uvec4(round(clamp(v, vec4(0.0), vec4(1.0)) * 255.0)); uvec4 uv = uvec4(round(clamp(v, vec4(0.0), vec4(1.0)) * 255.0));
return uv.x | uv.y << uint(8) | uv.z << uint(16) | uv.w << uint(24); return uv.x | (uv.y << uint(8)) | (uv.z << uint(16)) | (uv.w << uint(24));
} }
vec4 unpackUnorm4x8(uint p) { vec4 unpackUnorm4x8(uint p) {
return vec4(float(p & uint(0xffff)), float((p >> uint(8)) & uint(0xffff)), float((p >> uint(16)) & uint(0xffff)), float(p >> uint(24))) * 0.00392156862; // 1.0 / 255.0 return vec4(float(p & uint(0xff)), float((p >> uint(8)) & uint(0xff)), float((p >> uint(16)) & uint(0xff)), float(p >> uint(24))) * 0.00392156862; // 1.0 / 255.0
} }
uint packSnorm4x8(vec4 v) { uint packSnorm4x8(vec4 v) {
@ -55,6 +55,6 @@ uint packSnorm4x8(vec4 v) {
} }
vec4 unpackSnorm4x8(uint p) { vec4 unpackSnorm4x8(uint p) {
vec4 v = vec4(float(p & uint(0xffff)), float((p >> uint(8)) & uint(0xffff)), float((p >> uint(16)) & uint(0xffff)), float(p >> uint(24))); vec4 v = vec4(float(p & uint(0xff)), float((p >> uint(8)) & uint(0xff)), float((p >> uint(16)) & uint(0xff)), float(p >> uint(24)));
return clamp((v - vec4(127.0)) * vec4(0.00787401574), vec4(-1.0), vec4(1.0)); return clamp((v - vec4(127.0)) * vec4(0.00787401574), vec4(-1.0), vec4(1.0));
} }

View file

@ -92,11 +92,19 @@ vec3 tonemap_reinhard(vec3 color, float p_white) {
return (p_white * color + color) / (color * p_white + p_white); return (p_white * color + color) / (color * p_white + p_white);
} }
// This expects 0-1 range input.
vec3 linear_to_srgb(vec3 color) { vec3 linear_to_srgb(vec3 color) {
//if going to srgb, clamp from 0 to 1. //color = clamp(color, vec3(0.0), vec3(1.0));
color = clamp(color, vec3(0.0), vec3(1.0)); //const vec3 a = vec3(0.055f);
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)));
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))); // Approximation from http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
return max(vec3(1.055) * pow(color, vec3(0.416666667)) - vec3(0.055), vec3(0.0));
}
// This expects 0-1 range input, outside that range it behaves poorly.
vec3 srgb_to_linear(vec3 color) {
// Approximation from http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
return color * (color * (color * 0.305306011 + 0.682171111) + 0.012522878);
} }
#define TONEMAPPER_LINEAR 0 #define TONEMAPPER_LINEAR 0

View file

@ -1024,6 +1024,7 @@ MaterialData::~MaterialData() {
if (uniform_buffer) { if (uniform_buffer) {
glDeleteBuffers(1, &uniform_buffer); glDeleteBuffers(1, &uniform_buffer);
uniform_buffer = 0;
} }
} }
@ -1677,9 +1678,6 @@ ShaderCompiler::DefaultIdentifierActions actions;
//shaders.copy.initialize(); //shaders.copy.initialize();
//shaders.copy_version = shaders.copy.version_create(); //TODO //shaders.copy_version = shaders.copy.version_create(); //TODO
//shaders.copy.version_bind_shader(shaders.copy_version, CopyShaderGLES3::MODE_COPY_SECTION); //shaders.copy.version_bind_shader(shaders.copy_version, CopyShaderGLES3::MODE_COPY_SECTION);
//shaders.cubemap_filter.init();
//bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx");
//shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, !ggx_hq);
} }
MaterialStorage::~MaterialStorage() { MaterialStorage::~MaterialStorage() {
@ -3133,6 +3131,7 @@ GLES3::ShaderData *GLES3::_create_sky_shader_func() {
// Sky material // Sky material
void SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { void SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
uniform_set_updated = true;
return update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size); return update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
} }

View file

@ -45,6 +45,7 @@
#include "drivers/gles3/shaders/copy.glsl.gen.h" #include "drivers/gles3/shaders/copy.glsl.gen.h"
#include "../shaders/canvas.glsl.gen.h" #include "../shaders/canvas.glsl.gen.h"
#include "../shaders/cubemap_filter.glsl.gen.h"
#include "../shaders/scene.glsl.gen.h" #include "../shaders/scene.glsl.gen.h"
#include "../shaders/sky.glsl.gen.h" #include "../shaders/sky.glsl.gen.h"
@ -56,6 +57,7 @@ struct Shaders {
CanvasShaderGLES3 canvas_shader; CanvasShaderGLES3 canvas_shader;
SkyShaderGLES3 sky_shader; SkyShaderGLES3 sky_shader;
SceneShaderGLES3 scene_shader; SceneShaderGLES3 scene_shader;
CubemapFilterShaderGLES3 cubemap_filter_shader;
ShaderCompiler compiler_canvas; ShaderCompiler compiler_canvas;
ShaderCompiler compiler_scene; ShaderCompiler compiler_scene;
@ -241,6 +243,7 @@ ShaderData *_create_sky_shader_func();
struct SkyMaterialData : public MaterialData { struct SkyMaterialData : public MaterialData {
SkyShaderData *shader_data = nullptr; SkyShaderData *shader_data = nullptr;
bool uniform_set_updated = false;
virtual void set_render_priority(int p_priority) {} virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {} virtual void set_next_pass(RID p_pass) {}
@ -458,8 +461,6 @@ private:
SelfList<Material>::List material_update_list; SelfList<Material>::List material_update_list;
//static void _material_uniform_set_erased(void *p_material);
public: public:
static MaterialStorage *get_singleton(); static MaterialStorage *get_singleton();

View file

@ -570,24 +570,29 @@ void MeshStorage::mesh_clear(RID p_mesh) {
if (s.vertex_buffer != 0) { if (s.vertex_buffer != 0) {
glDeleteBuffers(1, &s.vertex_buffer); glDeleteBuffers(1, &s.vertex_buffer);
s.vertex_buffer = 0;
} }
if (s.version_count != 0) { if (s.version_count != 0) {
for (uint32_t j = 0; j < s.version_count; j++) { for (uint32_t j = 0; j < s.version_count; j++) {
glDeleteVertexArrays(1, &s.versions[j].vertex_array); glDeleteVertexArrays(1, &s.versions[j].vertex_array);
s.versions[j].vertex_array = 0;
} }
} }
if (s.attribute_buffer != 0) { if (s.attribute_buffer != 0) {
glDeleteBuffers(1, &s.attribute_buffer); glDeleteBuffers(1, &s.attribute_buffer);
s.attribute_buffer = 0;
} }
if (s.skin_buffer != 0) { if (s.skin_buffer != 0) {
glDeleteBuffers(1, &s.skin_buffer); glDeleteBuffers(1, &s.skin_buffer);
s.skin_buffer = 0;
} }
if (s.index_buffer != 0) { if (s.index_buffer != 0) {
glDeleteBuffers(1, &s.index_buffer); glDeleteBuffers(1, &s.index_buffer);
s.index_buffer = 0;
} }
memdelete(mesh->surfaces[i]); memdelete(mesh->surfaces[i]);
} }
@ -804,17 +809,20 @@ void MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
if (mi->surfaces[i].version_count != 0) { if (mi->surfaces[i].version_count != 0) {
for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) { for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) {
glDeleteVertexArrays(1, &mi->surfaces[i].versions[j].vertex_array); glDeleteVertexArrays(1, &mi->surfaces[i].versions[j].vertex_array);
mi->surfaces[i].versions[j].vertex_array = 0;
} }
memfree(mi->surfaces[i].versions); memfree(mi->surfaces[i].versions);
} }
if (mi->surfaces[i].vertex_buffer != 0) { if (mi->surfaces[i].vertex_buffer != 0) {
glDeleteBuffers(1, &mi->surfaces[i].vertex_buffer); glDeleteBuffers(1, &mi->surfaces[i].vertex_buffer);
mi->surfaces[i].vertex_buffer = 0;
} }
} }
mi->surfaces.clear(); mi->surfaces.clear();
if (mi->blend_weights_buffer != 0) { if (mi->blend_weights_buffer != 0) {
glDeleteBuffers(1, &mi->blend_weights_buffer); glDeleteBuffers(1, &mi->blend_weights_buffer);
mi->blend_weights_buffer = 0;
} }
mi->blend_weights.clear(); mi->blend_weights.clear();
mi->weights_dirty = false; mi->weights_dirty = false;

View file

@ -554,7 +554,7 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
} break; } break;
*/ */
default: { default: {
ERR_FAIL_V(Ref<Image>()); ERR_FAIL_V_MSG(Ref<Image>(), "Image Format: " + itos(p_format) + " is not supported by the OpenGL3 Renderer");
} }
} }
@ -968,7 +968,7 @@ void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image,
Image::Format real_format; Image::Format real_format;
Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), 0, real_format, format, internal_format, type, compressed, texture->resize_to_po2); Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), 0, real_format, format, internal_format, type, compressed, texture->resize_to_po2);
ERR_FAIL_COND(img.is_null());
if (texture->resize_to_po2) { if (texture->resize_to_po2) {
if (p_image->is_compressed()) { if (p_image->is_compressed()) {
ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage."); ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage.");
@ -1325,6 +1325,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
rt->color_internal_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? GL_RGBA8 : GL_RGB10_A2; rt->color_internal_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? GL_RGBA8 : GL_RGB10_A2;
rt->color_format = GL_RGBA; rt->color_format = GL_RGBA;
rt->color_type = rt->flags[RENDER_TARGET_TRANSPARENT] ? GL_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV;
rt->image_format = Image::FORMAT_RGBA8; rt->image_format = Image::FORMAT_RGBA8;
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);

View file

@ -249,7 +249,10 @@ struct Texture {
[[fallthrough]]; [[fallthrough]];
case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
pmag = GL_NEAREST; pmag = GL_NEAREST;
if (config->use_nearest_mip_filter) { if (mipmaps <= 1) {
pmin = GL_NEAREST;
max_lod = 0;
} else if (config->use_nearest_mip_filter) {
pmin = GL_NEAREST_MIPMAP_NEAREST; pmin = GL_NEAREST_MIPMAP_NEAREST;
} else { } else {
pmin = GL_NEAREST_MIPMAP_LINEAR; pmin = GL_NEAREST_MIPMAP_LINEAR;
@ -261,9 +264,11 @@ struct Texture {
[[fallthrough]]; [[fallthrough]];
case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
pmag = GL_LINEAR; pmag = GL_LINEAR;
if (config->use_nearest_mip_filter) { if (mipmaps <= 1) {
pmin = GL_LINEAR;
max_lod = 0;
} else if (config->use_nearest_mip_filter) {
pmin = GL_LINEAR_MIPMAP_NEAREST; pmin = GL_LINEAR_MIPMAP_NEAREST;
} else { } else {
pmin = GL_LINEAR_MIPMAP_LINEAR; pmin = GL_LINEAR_MIPMAP_LINEAR;
} }

View file

@ -1788,8 +1788,6 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
_validate_high_end("refraction", property); _validate_high_end("refraction", property);
_validate_high_end("subsurf_scatter", property); _validate_high_end("subsurf_scatter", property);
_validate_high_end("anisotropy", property);
_validate_high_end("clearcoat", property);
_validate_high_end("heightmap", property); _validate_high_end("heightmap", property);
if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) { if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) {

View file

@ -3006,8 +3006,8 @@ RenderingServer::RenderingServer() {
// OpenGL limits // OpenGL limits
GLOBAL_DEF_RST("rendering/limits/opengl/max_renderable_elements", 65536); GLOBAL_DEF_RST("rendering/limits/opengl/max_renderable_elements", 65536);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_renderable_elements", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_elements", PROPERTY_HINT_RANGE, "1024,65536,1")); ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_renderable_elements", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_elements", PROPERTY_HINT_RANGE, "1024,65536,1"));
GLOBAL_DEF_RST("rendering/limits/opengl/max_renderable_lights", 256); GLOBAL_DEF_RST("rendering/limits/opengl/max_renderable_lights", 32);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_renderable_lights", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_lights", PROPERTY_HINT_RANGE, "16,4096,1")); ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_renderable_lights", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_lights", PROPERTY_HINT_RANGE, "2,256,1"));
GLOBAL_DEF_RST("rendering/limits/opengl/max_lights_per_object", 8); GLOBAL_DEF_RST("rendering/limits/opengl/max_lights_per_object", 8);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_lights_per_object", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_lights_per_object", PROPERTY_HINT_RANGE, "2,1024,1")); ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_lights_per_object", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_lights_per_object", PROPERTY_HINT_RANGE, "2,1024,1"));