diff options
| -rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 45 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 8 | ||||
| -rw-r--r-- | drivers/gles3/shader_gles3.h | 7 | ||||
| -rw-r--r-- | drivers/gles3/shaders/SCsub | 1 | ||||
| -rw-r--r-- | drivers/gles3/shaders/scene.glsl | 2315 | ||||
| -rw-r--r-- | drivers/gles3/shaders/stdlib_inc.glsl | 3 | ||||
| -rw-r--r-- | drivers/gles3/storage/material_storage.cpp | 398 | ||||
| -rw-r--r-- | drivers/gles3/storage/material_storage.h | 126 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/light_data_inc.glsl | 32 | ||||
| -rw-r--r-- | servers/rendering/shader_compiler.cpp | 10 | 
10 files changed, 1171 insertions, 1774 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 8bb14e27e2..cabb06d837 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -708,6 +708,10 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *  		//ERR_FAIL_COND(!rt);  	} +	/////////// +	// Fill Light lists here +	////////// +  	Color clear_color;  	if (p_render_buffers.is_valid()) {  		clear_color = texture_storage->render_target_get_clear_request_color(rb->render_target); @@ -1053,6 +1057,38 @@ RasterizerSceneGLES3::RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage) {  	storage = p_storage;  	{ +		String global_defines; +		global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now +		material_storage->shaders.scene_shader.initialize(global_defines); +		scene_globals.shader_default_version = material_storage->shaders.scene_shader.version_create(); +		material_storage->shaders.scene_shader.version_bind_shader(scene_globals.shader_default_version, SceneShaderGLES3::MODE_COLOR); +	} + +	{ +		//default material and shader +		scene_globals.default_shader = material_storage->shader_allocate(); +		material_storage->shader_initialize(scene_globals.default_shader); +		material_storage->shader_set_code(scene_globals.default_shader, R"( +// Default 3D material shader (clustered). + +shader_type spatial; + +void vertex() { +	ROUGHNESS = 0.8; +} + +void fragment() { +	ALBEDO = vec3(0.6); +	ROUGHNESS = 0.8; +	METALLIC = 0.2; +} +)"); +		scene_globals.default_material = material_storage->material_allocate(); +		material_storage->material_initialize(scene_globals.default_material); +		material_storage->material_set_shader(scene_globals.default_material, scene_globals.default_shader); +	} + +	{  		// Initialize Sky stuff  		sky_globals.roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers");  		sky_globals.ggx_samples = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples"); @@ -1060,9 +1096,9 @@ RasterizerSceneGLES3::RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage) {  		String global_defines;  		global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now  		global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_globals.max_directional_lights) + "\n"; -		GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.initialize(global_defines); -		sky_globals.shader_default_version = GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_create(); -		GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_bind_shader(sky_globals.shader_default_version, SkyShaderGLES3::MODE_BACKGROUND); +		material_storage->shaders.sky_shader.initialize(global_defines); +		sky_globals.shader_default_version = material_storage->shaders.sky_shader.version_create(); +		material_storage->shaders.sky_shader.version_bind_shader(sky_globals.shader_default_version, SkyShaderGLES3::MODE_BACKGROUND);  	}  	{ @@ -1149,6 +1185,9 @@ void sky() {  }  RasterizerSceneGLES3::~RasterizerSceneGLES3() { +	GLES3::MaterialStorage::get_singleton()->shaders.scene_shader.version_free(scene_globals.shader_default_version); +	storage->free(scene_globals.default_material); +	storage->free(scene_globals.default_shader);  	GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_free(sky_globals.shader_default_version);  	storage->free(sky_globals.default_material);  	storage->free(sky_globals.default_shader); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 4c7502cda4..13b3b007a2 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -91,9 +91,7 @@ private:  	RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;  	uint64_t scene_pass = 0; -	/* Sky */  	struct SkyGlobals { -		RID shader_current_version;  		RID shader_default_version;  		RID default_material;  		RID default_shader; @@ -106,6 +104,12 @@ private:  		uint32_t ggx_samples = 128;  	} sky_globals; +	struct SceneGlobals { +		RID shader_default_version; +		RID default_material; +		RID default_shader; +	} scene_globals; +  protected:  	double time;  	double time_step = 0; diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 15281064af..8d1b142dc6 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -73,10 +73,11 @@ private:  	//versions  	CharString general_defines; -	// A version is a high-level construct which is a combination of built-in and user-defined shader code -	// Variants use #idefs to toggle behaviour on and off to change behaviour of the shader +	// A version is a high-level construct which is a combination of built-in and user-defined shader code, Each user-created Shader makes one version +	// Variants use #ifdefs to toggle behaviour on and off to change behaviour of the shader +	// All variants are compiled each time a new version is created  	// Specializations use #ifdefs to toggle behaviour on and off for performance, on supporting hardware, they will compile a version with everything enabled, and then compile more copies to improve performance -	// Use specializations to enable and disabled advanced features, use variants to toggle behaviour when different data may be used (e.g. using a samplerArray vs a sampler) +	// Use specializations to enable and disabled advanced features, use variants to toggle behaviour when different data may be used (e.g. using a samplerArray vs a sampler, or doing a depth prepass vs a color pass)  	struct Version {  		Vector<StringName> texture_uniforms;  		CharString uniforms; diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index 79247f38d4..ec32badc19 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -8,4 +8,5 @@ env.Depends("#drivers/gles3/shaders/copy.glsl.gen.h", "#core/math/transform_2d.h  if "GLES3_GLSL" in env["BUILDERS"]:      env.GLES3_GLSL("canvas.glsl")      env.GLES3_GLSL("copy.glsl") +    env.GLES3_GLSL("scene.glsl")      env.GLES3_GLSL("sky.glsl") diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index ebb00e81d0..16a9224fbb 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1,108 +1,146 @@  /* clang-format off */ -[vertex] +#[modes] -#ifdef USE_GLES_OVER_GL -#define lowp -#define mediump -#define highp -#else -precision highp float; -precision highp int; -#endif +mode_color = #define BASE_PASS +mode_additive = #define USE_ADDITIVE_LIGHTING +mode_depth = #define MODE_RENDER_DEPTH + +#[specializations] -#define SHADER_IS_SRGB true //TODO remove +USE_LIGHTMAP = false +USE_LIGHT_DIRECTIONAL = false +USE_LIGHT_POSITIONAL = false + + +#[vertex]  #define M_PI 3.14159265359 -// -// attributes -// +#define SHADER_IS_SRGB true + +#include "stdlib_inc.glsl" + +/* +from RenderingServer: +ARRAY_VERTEX = 0, // RG32F or RGB32F (depending on 2D bit) +ARRAY_COLOR = 3, // RGBA8 +ARRAY_TEX_UV = 4, // RG32F +ARRAY_TANGENT = 2, // A2B10G10R10, A flips sign of binormal. +ARRAY_NORMAL = 1, // A2B10G10R10, A is ignored. +ARRAY_TEX_UV2 = 5, // RG32F +ARRAY_CUSTOM0 = 6, // Depends on ArrayCustomFormat. +ARRAY_CUSTOM1 = 7, +ARRAY_CUSTOM2 = 8, +ARRAY_CUSTOM3 = 9, +ARRAY_BONES = 10, // RGBA16UI (x2 if 8 weights) +ARRAY_WEIGHTS = 11, // RGBA16UNORM (x2 if 8 weights) +ARRAY_INDEX = 12, // 16 or 32 bits depending on length > 0xFFFF. +ARRAY_MAX = 13 +*/ + +/* INPUT ATTRIBS */ -layout(location = 0) in highp vec4 vertex_attrib; +layout(location = 0) in vec3 vertex_attrib;  /* clang-format on */ + +#ifdef NORMAL_USED  layout(location = 1) in vec3 normal_attrib; +#endif -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)  layout(location = 2) in vec4 tangent_attrib;  #endif -#if defined(ENABLE_COLOR_INTERP) +#if defined(COLOR_USED)  layout(location = 3) in vec4 color_attrib;  #endif -#if defined(ENABLE_UV_INTERP) +#ifdef UV_USED  layout(location = 4) in vec2 uv_attrib;  #endif -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) +#if defined(UV2_USED) || defined(USE_LIGHTMAP)  layout(location = 5) in vec2 uv2_attrib;  #endif -#ifdef USE_SKELETON - -#ifdef USE_SKELETON_SOFTWARE - -layout(location = 13) in highp vec4 bone_transform_row_0; -layout(location = 14) in highp vec4 bone_transform_row_1; -layout(location = 15) in highp vec4 bone_transform_row_2; +#if defined(CUSTOM0_USED) +layout(location = 6) in vec4 custom0_attrib; +#endif -#else +#if defined(CUSTOM1_USED) +layout(location = 7) in vec4 custom1_attrib; +#endif -layout(location = 6) in vec4 bone_ids; -layout(location = 7) in highp vec4 bone_weights; +#if defined(CUSTOM2_USED) +layout(location = 8) in vec4 custom2_attrib; +#endif -uniform highp sampler2D bone_transforms; // texunit:-1 -uniform ivec2 skeleton_texture_size; +#if defined(CUSTOM3_USED) +layout(location = 9) in vec4 custom3_attrib; +#endif +#if defined(BONES_USED) || defined(USE_PARTICLE_TRAILS) +layout(location = 10) in uvec4 bone_attrib;  #endif +#if defined(WEIGHTS_USED) || defined(USE_PARTICLE_TRAILS) +layout(location = 11) in vec4 weight_attrib;  #endif -#ifdef USE_INSTANCING +layout(std140) uniform SceneData { // ubo:3 +	mat4 projection_matrix; +	mat4 inv_projection_matrix; +	mat4 inv_view_matrix; +	mat4 view_matrix; -layout(location = 8) in highp vec4 instance_xform_row_0; -layout(location = 9) in highp vec4 instance_xform_row_1; -layout(location = 10) in highp vec4 instance_xform_row_2; +	vec2 viewport_size; +	vec2 screen_pixel_size; -layout(location = 11) in highp vec4 instance_color; -layout(location = 12) in highp vec4 instance_custom_data; +	mediump vec4 ambient_light_color_energy; -#endif +	mediump float ambient_color_sky_mix; +	uint ambient_flags; +	bool material_uv2_mode; +	float opaque_prepass_threshold; +	//bool use_ambient_light; +	//bool use_ambient_cubemap; +	//bool use_reflection_cubemap; -// -// uniforms -// +	mat3 radiance_inverse_xform; -uniform highp mat4 inv_view_matrix; -uniform highp mat4 view_matrix; -uniform highp mat4 projection_matrix; -uniform highp mat4 projection_inverse_matrix; +	uint directional_light_count; +	float z_far; +	float z_near; +	float pad; -uniform highp mat4 world_transform; +	bool fog_enabled; +	float fog_density; +	float fog_height; +	float fog_height_density; -uniform highp float time; +	vec3 fog_light_color; +	float fog_sun_scatter; -uniform highp vec2 viewport_size; +	float fog_aerial_perspective; -#ifdef RENDER_DEPTH -uniform float light_bias; -uniform float light_normal_bias; -#endif +	float time; +	float reflection_multiplier; // one normally, zero when rendering reflections -// -// varyings -// +	bool pancake_shadows; +} +scene_data; -#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS) -out highp vec4 position_interp; +uniform highp mat4 world_transform; + +#ifdef USE_LIGHTMAP +uniform highp vec4 lightmap_uv_rect;  #endif +/* Varyings */ +  out highp vec3 vertex_interp; +#ifdef NORMAL_USED  out vec3 normal_interp; - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -out vec3 tangent_interp; -out vec3 binormal_interp;  #endif  #if defined(ENABLE_COLOR_INTERP) @@ -113,537 +151,155 @@ out vec4 color_interp;  out vec2 uv_interp;  #endif -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) +#if defined(ENABLE_UV2_INTERP)  out vec2 uv2_interp; -#endif - -/* clang-format off */ - -VERTEX_SHADER_GLOBALS - -/* clang-format on */ - -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - -out highp float dp_clip; -uniform highp float shadow_dual_paraboloid_render_zfar; -uniform highp float shadow_dual_paraboloid_render_side; - -#endif - -#if defined(USE_SHADOW) && defined(USE_LIGHTING) - -uniform highp mat4 light_shadow_matrix; -out highp vec4 shadow_coord; - -#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) -uniform highp mat4 light_shadow_matrix2; -out highp vec4 shadow_coord2; -#endif - -#if defined(LIGHT_USE_PSSM4) - -uniform highp mat4 light_shadow_matrix3; -uniform highp mat4 light_shadow_matrix4; -out highp vec4 shadow_coord3; -out highp vec4 shadow_coord4; - -#endif - -#endif - -#if defined(USE_VERTEX_LIGHTING) && defined(USE_LIGHTING) - -out highp vec3 diffuse_interp; -out highp vec3 specular_interp; - -// general for all lights -uniform highp vec4 light_color; -uniform highp vec4 shadow_color; -uniform highp float light_specular; - -// directional -uniform highp vec3 light_direction; - -// omni -uniform highp vec3 light_position; - -uniform highp float light_range; -uniform highp float light_attenuation; - -// spot -uniform highp float light_spot_attenuation; -uniform highp float light_spot_range; -uniform highp float light_spot_angle; - -void light_compute( -		vec3 N, -		vec3 L, -		vec3 V, -		vec3 light_color, -		vec3 attenuation, -		float roughness) { -//this makes lights behave closer to linear, but then addition of lights looks bad -//better left disabled - -//#define SRGB_APPROX(m_var) m_var = pow(m_var,0.4545454545); -/* -#define SRGB_APPROX(m_var) {\ -	float S1 = sqrt(m_var);\ -	float S2 = sqrt(S1);\ -	float S3 = sqrt(S2);\ -	m_var = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.0225411470 * m_var;\ -	} -*/ -#define SRGB_APPROX(m_var) - -	float NdotL = dot(N, L); -	float cNdotL = max(NdotL, 0.0); // clamped NdotL -	float NdotV = dot(N, V); -	float cNdotV = max(NdotV, 0.0); - -#if defined(DIFFUSE_OREN_NAYAR) -	vec3 diffuse_brdf_NL;  #else -	float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance -#endif - -#if defined(DIFFUSE_LAMBERT_WRAP) -	// energy conserving lambert wrap shader -	diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); - -#elif defined(DIFFUSE_OREN_NAYAR) - -	{ -		// see http://mimosa-pudica.net/improved-oren-nayar.html -		float LdotV = dot(L, V); - -		float s = LdotV - NdotL * NdotV; -		float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); - -		float sigma2 = roughness * roughness; // TODO: this needs checking -		vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13)); -		float B = 0.45 * sigma2 / (sigma2 + 0.09); - -		diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); -	} -#else -	// lambert by default for everything else -	diffuse_brdf_NL = cNdotL * (1.0 / M_PI); +#ifdef USE_LIGHTMAP +out vec2 uv2_interp;  #endif - -	SRGB_APPROX(diffuse_brdf_NL) - -	diffuse_interp += light_color * diffuse_brdf_NL * attenuation; - -	if (roughness > 0.0) { -		// D -		float specular_brdf_NL = 0.0; - -#if !defined(SPECULAR_DISABLED) -		//normalized blinn always unless disabled -		vec3 H = normalize(V + L); -		float cNdotH = max(dot(N, H), 0.0); -		float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; -		float blinn = pow(cNdotH, shininess) * cNdotL; -		blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); -		specular_brdf_NL = blinn;  #endif -		SRGB_APPROX(specular_brdf_NL) -		specular_interp += specular_brdf_NL * light_color * attenuation * (1.0 / M_PI); -	} -} - +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) +out vec3 tangent_interp; +out vec3 binormal_interp;  #endif -#ifdef USE_VERTEX_LIGHTING - -#ifdef USE_REFLECTION_PROBE1 - -uniform highp mat4 refprobe1_local_matrix; -out mediump vec4 refprobe1_reflection_normal_blend; -uniform highp vec3 refprobe1_box_extents; +#if defined(USE_MATERIAL) -#ifndef USE_LIGHTMAP -out mediump vec3 refprobe1_ambient_normal; -#endif - -#endif //reflection probe1 +/* clang-format off */ +layout(std140) uniform UniformData { // ubo:1 -#ifdef USE_REFLECTION_PROBE2 +#MATERIAL_UNIFORMS -uniform highp mat4 refprobe2_local_matrix; -out mediump vec4 refprobe2_reflection_normal_blend; -uniform highp vec3 refprobe2_box_extents; +}; +/* clang-format on */ -#ifndef USE_LIGHTMAP -out mediump vec3 refprobe2_ambient_normal;  #endif -#endif //reflection probe2 - -#endif //vertex lighting for refprobes - -#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - -out vec4 fog_interp; - -uniform mediump vec4 fog_color_base; -#ifdef LIGHT_MODE_DIRECTIONAL -uniform mediump vec4 fog_sun_color_amount; -#endif +/* clang-format off */ -uniform bool fog_transmit_enabled; -uniform mediump float fog_transmit_curve; +#GLOBALS -#ifdef FOG_DEPTH_ENABLED -uniform highp float fog_depth_begin; -uniform mediump float fog_depth_curve; -uniform mediump float fog_max_distance; -#endif +/* clang-format on */ -#ifdef FOG_HEIGHT_ENABLED -uniform highp float fog_height_min; -uniform highp float fog_height_max; -uniform mediump float fog_height_curve; -#endif +out highp vec4 position_interp; -#endif //fog +invariant gl_Position;  void main() { -	highp vec4 vertex = vertex_attrib; +	highp vec3 vertex = vertex_attrib; -	mat4 model_matrix = world_transform; - -#ifdef USE_INSTANCING -	{ -		highp mat4 m = mat4( -				instance_xform_row_0, -				instance_xform_row_1, -				instance_xform_row_2, -				vec4(0.0, 0.0, 0.0, 1.0)); -		model_matrix = model_matrix * transpose(m); -	} +	highp mat4 model_matrix = world_transform; +#ifdef NORMAL_USED +	vec3 normal = normal_attrib * 2.0 - 1.0;  #endif +	mat3 model_normal_matrix = mat3(model_matrix); -	vec3 normal = normal_attrib; - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -	vec3 tangent = tangent_attrib.xyz; -	float binormalf = tangent_attrib.a; -	vec3 binormal = normalize(cross(normal, tangent) * binormalf); +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) +	vec3 tangent; +	float binormalf; +	tangent = normal_tangent_attrib.xyz; +	binormalf = normal_tangent_attrib.a;  #endif  #if defined(ENABLE_COLOR_INTERP)  	color_interp = color_attrib; -#ifdef USE_INSTANCING -	color_interp *= instance_color;  #endif + +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) +	vec3 binormal = normalize(cross(normal, tangent) * binormalf);  #endif  #if defined(ENABLE_UV_INTERP)  	uv_interp = uv_attrib;  #endif -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) +#ifdef USE_LIGHTMAP +	uv2_interp = lightmap_uv_rect.zw * uv2_attrib + lightmap_uv_rect.xy; +#else +#if defined(ENABLE_UV2_INTERP)  	uv2_interp = uv2_attrib;  #endif +#endif  #if defined(OVERRIDE_POSITION)  	highp vec4 position;  #endif +	mat4 projection_matrix = scene_data.projection_matrix; +	mat4 inv_projection_matrix = scene_data.inv_projection_matrix; -#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) -	vertex = model_matrix * vertex; -	normal = normalize((model_matrix * vec4(normal, 0.0)).xyz); -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - -	tangent = normalize((model_matrix * vec4(tangent, 0.0)).xyz); -	binormal = normalize((model_matrix * vec4(binormal, 0.0)).xyz); -#endif -#endif - -#ifdef USE_SKELETON - -	highp mat4 bone_transform = mat4(0.0); - -#ifdef USE_SKELETON_SOFTWARE -	// passing the transform as attributes - -	bone_transform[0] = vec4(bone_transform_row_0.x, bone_transform_row_1.x, bone_transform_row_2.x, 0.0); -	bone_transform[1] = vec4(bone_transform_row_0.y, bone_transform_row_1.y, bone_transform_row_2.y, 0.0); -	bone_transform[2] = vec4(bone_transform_row_0.z, bone_transform_row_1.z, bone_transform_row_2.z, 0.0); -	bone_transform[3] = vec4(bone_transform_row_0.w, bone_transform_row_1.w, bone_transform_row_2.w, 1.0); +	vec4 instance_custom = vec4(0.0); -#else -	// look up transform from the "pose texture" -	{ -		for (int i = 0; i < 4; i++) { -			ivec2 tex_ofs = ivec2(int(bone_ids[i]) * 3, 0); +	// Using world coordinates +#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) -			highp mat4 b = mat4( -					texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(0, 0)), -					texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(1, 0)), -					texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(2, 0)), -					vec4(0.0, 0.0, 0.0, 1.0)); - -			bone_transform += transpose(b) * bone_weights[i]; -		} -	} +	vertex = (model_matrix * vec4(vertex, 1.0)).xyz; +#ifdef NORMAL_USED +	normal = model_normal_matrix * normal;  #endif -	model_matrix = model_matrix * bone_transform; - -#endif +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -#ifdef USE_INSTANCING -	vec4 instance_custom = instance_custom_data; -#else -	vec4 instance_custom = vec4(0.0); +	tangent = model_normal_matrix * tangent; +	binormal = model_normal_matrix * binormal;  #endif +#endif -	mat4 local_projection_matrix = projection_matrix; - -	mat4 modelview = view_matrix * model_matrix;  	float roughness = 1.0; -#define projection_matrix local_projection_matrix -#define world_transform model_matrix +	mat4 modelview = scene_data.view_matrix * model_matrix; +	mat3 modelview_normal = mat3(scene_data.view_matrix) * model_normal_matrix;  	float point_size = 1.0;  	{ -		/* clang-format off */ - -VERTEX_SHADER_CODE - -		/* clang-format on */ +#CODE : VERTEX  	}  	gl_PointSize = point_size; -	vec4 outvec = vertex; -	// use local coordinates +	// Using local coordinates (default)  #if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED) -	vertex = modelview * vertex; -	normal = normalize((modelview * vec4(normal, 0.0)).xyz); - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -	tangent = normalize((modelview * vec4(tangent, 0.0)).xyz); -	binormal = normalize((modelview * vec4(binormal, 0.0)).xyz); -#endif -#endif - -#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) -	vertex = view_matrix * vertex; -	normal = normalize((view_matrix * vec4(normal, 0.0)).xyz); -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -	tangent = normalize((view_matrix * vec4(tangent, 0.0)).xyz); -	binormal = normalize((view_matrix * vec4(binormal, 0.0)).xyz); -#endif -#endif - -	vertex_interp = vertex.xyz; -	normal_interp = normal; - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -	tangent_interp = tangent; -	binormal_interp = binormal; -#endif - -#ifdef RENDER_DEPTH - -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - -	vertex_interp.z *= shadow_dual_paraboloid_render_side; -	normal_interp.z *= shadow_dual_paraboloid_render_side; - -	dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias - -	//for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges - -	highp vec3 vtx = vertex_interp + normalize(vertex_interp) * light_bias; -	highp float distance = length(vtx); -	vtx = normalize(vtx); -	vtx.xy /= 1.0 - vtx.z; -	vtx.z = (distance / shadow_dual_paraboloid_render_zfar); -	vtx.z = vtx.z * 2.0 - 1.0; - -	vertex_interp = vtx; - -#else -	float z_ofs = light_bias; -	z_ofs += (1.0 - abs(normal_interp.z)) * light_normal_bias; - -	vertex_interp.z -= z_ofs; -#endif //dual parabolloid - -#endif //depth - -//vertex lighting -#if defined(USE_VERTEX_LIGHTING) && defined(USE_LIGHTING) -	//vertex shaded version of lighting (more limited) -	vec3 L; -	vec3 light_att; - -#ifdef LIGHT_MODE_OMNI -	vec3 light_vec = light_position - vertex_interp; -	float light_length = length(light_vec); - -	float normalized_distance = light_length / light_range; - -	if (normalized_distance < 1.0) { -		float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation); - -		vec3 attenuation = vec3(omni_attenuation); -		light_att = vec3(omni_attenuation); -	} else { -		light_att = vec3(0.0); -	} - -	L = normalize(light_vec); - -#endif - -#ifdef LIGHT_MODE_SPOT - -	vec3 light_rel_vec = light_position - vertex_interp; -	float light_length = length(light_rel_vec); -	float normalized_distance = light_length / light_range; - -	if (normalized_distance < 1.0) { -		float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation); -		vec3 spot_dir = light_direction; - -		float spot_cutoff = light_spot_angle; - -		float angle = dot(-normalize(light_rel_vec), spot_dir); - -		if (angle > spot_cutoff) { -			float scos = max(angle, spot_cutoff); -			float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff)); - -			spot_attenuation *= 1.0 - pow(spot_rim, light_spot_attenuation); - -			light_att = vec3(spot_attenuation); -		} else { -			light_att = vec3(0.0); -		} -	} else { -		light_att = vec3(0.0); -	} - -	L = normalize(light_rel_vec); +	vertex = (modelview * vec4(vertex, 1.0)).xyz; +#ifdef NORMAL_USED +	normal = modelview_normal * normal;  #endif -#ifdef LIGHT_MODE_DIRECTIONAL -	vec3 light_vec = -light_direction; -	light_att = vec3(1.0); //no base attenuation -	L = normalize(light_vec);  #endif -	diffuse_interp = vec3(0.0); -	specular_interp = vec3(0.0); -	light_compute(normal_interp, L, -normalize(vertex_interp), light_color.rgb, light_att, roughness); - -#endif - -//shadows (for both vertex and fragment) -#if defined(USE_SHADOW) && defined(USE_LIGHTING) - -	vec4 vi4 = vec4(vertex_interp, 1.0); -	shadow_coord = light_shadow_matrix * vi4; +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) -	shadow_coord2 = light_shadow_matrix2 * vi4; +	binormal = modelview_normal * binormal; +	tangent = modelview_normal * tangent;  #endif -#if defined(LIGHT_USE_PSSM4) -	shadow_coord3 = light_shadow_matrix3 * vi4; -	shadow_coord4 = light_shadow_matrix4 * vi4; +	// Using world coordinates +#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) +	vertex = (scene_data.view_matrix * vec4(vertex, 1.0)).xyz; +#ifdef NORMAL_USED +	normal = (scene_data.view_matrix * vec4(normal, 0.0)).xyz;  #endif -#endif //use shadow and use lighting - -#ifdef USE_VERTEX_LIGHTING - -#ifdef USE_REFLECTION_PROBE1 -	{ -		vec3 ref_normal = normalize(reflect(vertex_interp, normal_interp)); -		vec3 local_pos = (refprobe1_local_matrix * vec4(vertex_interp, 1.0)).xyz; -		vec3 inner_pos = abs(local_pos / refprobe1_box_extents); -		float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); - -		{ -			vec3 local_ref_vec = (refprobe1_local_matrix * vec4(ref_normal, 0.0)).xyz; -			refprobe1_reflection_normal_blend.xyz = local_ref_vec; -			refprobe1_reflection_normal_blend.a = blend; -		} -#ifndef USE_LIGHTMAP - -		refprobe1_ambient_normal = (refprobe1_local_matrix * vec4(normal_interp, 0.0)).xyz; +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) +	binormal = (scene_data.view_matrix * vec4(binormal, 0.0)).xyz; +	tangent = (scene_data.view_matrix * vec4(tangent, 0.0)).xyz;  #endif -	} - -#endif //USE_REFLECTION_PROBE1 - -#ifdef USE_REFLECTION_PROBE2 -	{ -		vec3 ref_normal = normalize(reflect(vertex_interp, normal_interp)); -		vec3 local_pos = (refprobe2_local_matrix * vec4(vertex_interp, 1.0)).xyz; -		vec3 inner_pos = abs(local_pos / refprobe2_box_extents); -		float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); - -		{ -			vec3 local_ref_vec = (refprobe2_local_matrix * vec4(ref_normal, 0.0)).xyz; -			refprobe2_reflection_normal_blend.xyz = local_ref_vec; -			refprobe2_reflection_normal_blend.a = blend; -		} -#ifndef USE_LIGHTMAP - -		refprobe2_ambient_normal = (refprobe2_local_matrix * vec4(normal_interp, 0.0)).xyz;  #endif -	} - -#endif //USE_REFLECTION_PROBE2 - -#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - -	float fog_amount = 0.0; - -#ifdef LIGHT_MODE_DIRECTIONAL -	vec3 fog_color = mix(fog_color_base.rgb, fog_sun_color_amount.rgb, fog_sun_color_amount.a * pow(max(dot(normalize(vertex_interp), light_direction), 0.0), 8.0)); -#else -	vec3 fog_color = fog_color_base.rgb; -#endif - -#ifdef FOG_DEPTH_ENABLED - -	{ -		float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex)); - -		fog_amount = pow(fog_z, fog_depth_curve) * fog_color_base.a; -	} +	vertex_interp = vertex; +#ifdef NORMAL_USED +	normal_interp = normal;  #endif -#ifdef FOG_HEIGHT_ENABLED -	{ -		float y = (inv_view_matrix * vec4(vertex_interp, 1.0)).y; -		fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve)); -	} +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) +	tangent_interp = tangent; +	binormal_interp = binormal;  #endif -	fog_interp = vec4(fog_color, fog_amount); - -#endif //fog - -#endif //use vertex lighting  #if defined(OVERRIDE_POSITION)  	gl_Position = position; @@ -651,333 +307,230 @@ VERTEX_SHADER_CODE  	gl_Position = projection_matrix * vec4(vertex_interp, 1.0);  #endif -#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS) -	position_interp = gl_Position; +#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 */ -[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 -#define SHADER_IS_SRGB true - -// -// uniforms -// - -uniform highp mat4 inv_view_matrix; -/* clang-format on */ -uniform highp mat4 view_matrix; -uniform highp mat4 projection_matrix; -uniform highp mat4 projection_inverse_matrix; - -uniform highp mat4 world_transform; +#[fragment] -uniform highp float time; -uniform highp vec2 viewport_size; - -#if defined(SCREEN_UV_USED) -uniform vec2 screen_pixel_size; +// Default to SPECULAR_SCHLICK_GGX. +#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_TOON) +#define SPECULAR_SCHLICK_GGX  #endif -#if defined(SCREEN_TEXTURE_USED) -uniform highp sampler2D screen_texture; //texunit:-4 -#endif -#if defined(DEPTH_TEXTURE_USED) -uniform highp sampler2D depth_texture; //texunit:-4 +#if !defined(MODE_RENDER_DEPTH) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) +#ifndef NORMAL_USED +#define NORMAL_USED  #endif - -#ifdef USE_REFLECTION_PROBE1 - -#ifdef USE_VERTEX_LIGHTING - -in mediump vec4 refprobe1_reflection_normal_blend; -#ifndef USE_LIGHTMAP -in mediump vec3 refprobe1_ambient_normal;  #endif -#else - -uniform bool refprobe1_use_box_project; -uniform highp vec3 refprobe1_box_extents; -uniform vec3 refprobe1_box_offset; -uniform highp mat4 refprobe1_local_matrix; +#include "tonemap_inc.glsl" +#include "stdlib_inc.glsl" -#endif //use vertex lighting +/* texture unit usage, N is max_texture_unity-N -uniform bool refprobe1_exterior; +1-color correction // In tonemap_inc.glsl +2-radiance +3-directional_shadow +4-positional_shadow +5-screen +6-depth -uniform highp samplerCube reflection_probe1; //texunit:-5 +*/ -uniform float refprobe1_intensity; -uniform vec4 refprobe1_ambient; +uniform highp mat4 world_transform; +/* clang-format on */ -#endif //USE_REFLECTION_PROBE1 +#define M_PI 3.14159265359 +#define SHADER_IS_SRGB false -#ifdef USE_REFLECTION_PROBE2 +/* Varyings */ -#ifdef USE_VERTEX_LIGHTING +#if defined(ENABLE_COLOR_INTERP) +in vec4 color_interp; +#endif -in mediump vec4 refprobe2_reflection_normal_blend; -#ifndef USE_LIGHTMAP -in mediump vec3 refprobe2_ambient_normal; +#if defined(ENABLE_UV_INTERP) +in vec2 uv_interp;  #endif +#if defined(ENABLE_UV2_INTERP) +in vec2 uv2_interp;  #else - -uniform bool refprobe2_use_box_project; -uniform highp vec3 refprobe2_box_extents; -uniform vec3 refprobe2_box_offset; -uniform highp mat4 refprobe2_local_matrix; - -#endif //use vertex lighting - -uniform bool refprobe2_exterior; - -uniform highp samplerCube reflection_probe2; //texunit:-6 - -uniform float refprobe2_intensity; -uniform vec4 refprobe2_ambient; - -#endif //USE_REFLECTION_PROBE2 - -#define RADIANCE_MAX_LOD 6.0 - -#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) - -void reflection_process(samplerCube reflection_map, -#ifdef USE_VERTEX_LIGHTING -		vec3 ref_normal, -#ifndef USE_LIGHTMAP -		vec3 amb_normal, +#ifdef USE_LIGHTMAP +in vec2 uv2_interp; +#endif  #endif -		float ref_blend, - -#else //no vertex lighting -		vec3 normal, vec3 vertex, -		mat4 local_matrix, -		bool use_box_project, vec3 box_extents, vec3 box_offset, -#endif //vertex lighting -		bool exterior, float intensity, vec4 ref_ambient, float roughness, vec3 ambient, vec3 skybox, inout highp vec4 reflection_accum, inout highp vec4 ambient_accum) { -	vec4 reflection; - -#ifdef USE_VERTEX_LIGHTING - -	reflection.rgb = textureCubeLod(reflection_map, ref_normal, roughness * RADIANCE_MAX_LOD).rgb; - -	float blend = ref_blend; //crappier blend formula for vertex -	blend *= blend; -	blend = max(0.0, 1.0 - blend); - -#else //fragment lighting - -	vec3 local_pos = (local_matrix * vec4(vertex, 1.0)).xyz; - -	if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box -		return; -	} - -	vec3 inner_pos = abs(local_pos / box_extents); -	float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); -	blend = mix(length(inner_pos), blend, blend); -	blend *= blend; -	blend = max(0.0, 1.0 - blend); - -	//reflect and make local -	vec3 ref_normal = normalize(reflect(vertex, normal)); -	ref_normal = (local_matrix * vec4(ref_normal, 0.0)).xyz; - -	if (use_box_project) { //box project - -		vec3 nrdir = normalize(ref_normal); -		vec3 rbmax = (box_extents - local_pos) / nrdir; -		vec3 rbmin = (-box_extents - local_pos) / nrdir; - -		vec3 rbminmax = mix(rbmin, rbmax, vec3(greaterThan(nrdir, vec3(0.0, 0.0, 0.0)))); - -		float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z); -		vec3 posonbox = local_pos + nrdir * fa; -		ref_normal = posonbox - box_offset.xyz; -	} -	reflection.rgb = textureCubeLod(reflection_map, ref_normal, roughness * RADIANCE_MAX_LOD).rgb; +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) +in vec3 tangent_interp; +in vec3 binormal_interp;  #endif -	if (exterior) { -		reflection.rgb = mix(skybox, reflection.rgb, blend); -	} -	reflection.rgb *= intensity; -	reflection.a = blend; -	reflection.rgb *= blend; +in highp vec3 vertex_interp; +in vec3 normal_interp; -	reflection_accum += reflection; +/* PBR CHANNELS */ -#ifndef USE_LIGHTMAP +#ifdef USE_RADIANCE_MAP -	vec4 ambient_out; -#ifndef USE_VERTEX_LIGHTING +layout(std140) uniform Radiance { // ubo:2 -	vec3 amb_normal = (local_matrix * vec4(normal, 0.0)).xyz; -#endif +	mat4 radiance_inverse_xform; +	float radiance_ambient_contribution; +}; -	ambient_out.rgb = textureCubeLod(reflection_map, amb_normal, RADIANCE_MAX_LOD).rgb; -	ambient_out.rgb = mix(ref_ambient.rgb, ambient_out.rgb, ref_ambient.a); -	if (exterior) { -		ambient_out.rgb = mix(ambient, ambient_out.rgb, blend); -	} +#define RADIANCE_MAX_LOD 5.0 -	ambient_out.a = blend; -	ambient_out.rgb *= blend; -	ambient_accum += ambient_out; +uniform sampler2D radiance_map; // texunit:-2 -#endif +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 //use refprobe 1 or 2 - -#ifdef USE_LIGHTMAP -uniform mediump sampler2D lightmap; //texunit:-4 -uniform mediump float lightmap_energy;  #endif -#ifdef USE_LIGHTMAP_CAPTURE -uniform mediump vec4[12] lightmap_captures; -uniform bool lightmap_capture_sky; +/* Material Uniforms */ -#endif +#if defined(USE_MATERIAL) -#ifdef USE_RADIANCE_MAP +/* clang-format off */ +layout(std140) uniform UniformData { -uniform samplerCube radiance_map; // texunit:-2 +#MATERIAL_UNIFORMS -uniform mat4 radiance_inverse_xform; +}; +/* clang-format on */  #endif -uniform vec4 bg_color; -uniform float bg_energy; - -uniform float ambient_sky_contribution; -uniform vec4 ambient_color; -uniform float ambient_energy; +layout(std140) uniform SceneData { // ubo:3 +	mat4 projection_matrix; +	mat4 inv_projection_matrix; +	mat4 inv_view_matrix; +	mat4 view_matrix; -#ifdef USE_LIGHTING +	vec2 viewport_size; +	vec2 screen_pixel_size; -uniform highp vec4 shadow_color; +	mediump vec4 ambient_light_color_energy; -#ifdef USE_VERTEX_LIGHTING +	mediump float ambient_color_sky_mix; +	uint ambient_flags; +	bool material_uv2_mode; +	float opaque_prepass_threshold; +	//bool use_ambient_light; +	//bool use_ambient_cubemap; +	//bool use_reflection_cubemap; -//get from vertex -in highp vec3 diffuse_interp; -in highp vec3 specular_interp; +	mat3 radiance_inverse_xform; -uniform highp vec3 light_direction; //may be used by fog, so leave here +	uint directional_light_count; +	float z_far; +	float z_near; +	float pad; -#else -//done in fragment -// general for all lights -uniform highp vec4 light_color; +	bool fog_enabled; +	float fog_density; +	float fog_height; +	float fog_height_density; -uniform highp float light_specular; +	vec3 fog_light_color; +	float fog_sun_scatter; -// directional -uniform highp vec3 light_direction; -// omni -uniform highp vec3 light_position; +	float fog_aerial_perspective; -uniform highp float light_attenuation; +	float time; +	float reflection_multiplier; // one normally, zero when rendering reflections -// spot -uniform highp float light_spot_attenuation; -uniform highp float light_spot_range; -uniform highp float light_spot_angle; -#endif +	bool pancake_shadows; +} +scene_data; -//this is needed outside above if because dual paraboloid wants it -uniform highp float light_range; +/* clang-format off */ -#ifdef USE_SHADOW +#GLOBALS -uniform highp vec2 shadow_pixel_size; +/* clang-format on */ -#if defined(LIGHT_MODE_OMNI) || defined(LIGHT_MODE_SPOT) -uniform highp sampler2D light_shadow_atlas; //texunit:-3 -#endif +//directional light data -#ifdef LIGHT_MODE_DIRECTIONAL -uniform highp sampler2D light_directional_shadow; // texunit:-3 -uniform highp vec4 light_split_offsets; -#endif +#ifdef USE_LIGHT_DIRECTIONAL -in highp vec4 shadow_coord; +struct DirectionalLightData { +	mediump vec3 direction; +	mediump float energy; +	mediump vec3 color; +	mediump float size; +	mediump vec3 pad; +	mediump float specular; +}; -#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) -in highp vec4 shadow_coord2;  #endif -#if defined(LIGHT_USE_PSSM4) - -in highp vec4 shadow_coord3; -in highp vec4 shadow_coord4; +// omni and spot +#ifdef USE_LIGHT_POSITIONAL +struct LightData { //this structure needs to be as packed as possible +	highp vec3 position; +	highp float inv_radius; -#endif +	mediump vec3 direction; +	highp float size; -uniform vec4 light_clamp; +	mediump vec3 color; +	mediump float attenuation; -#endif // light shadow +	mediump float cone_attenuation; +	mediump float cone_angle; +	mediump float specular_amount; +	bool shadow_enabled; +}; -// directional shadow +layout(std140) uniform OmniLightData { // ubo:4 -#endif +	LightData omni_lights[MAX_LIGHT_DATA_STRUCTS]; +}; -// -// varyings -// +layout(std140) uniform SpotLightData { // ubo:5 -#if defined(RENDER_DEPTH) && defined(USE_RGBA_SHADOWS) -in highp vec4 position_interp; -#endif +	LightData spot_lights[MAX_LIGHT_DATA_STRUCTS]; +}; -in highp vec3 vertex_interp; -in vec3 normal_interp; +uniform highp samplerCubeShadow positional_shadow; // texunit:-6 -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -in vec3 tangent_interp; -in vec3 binormal_interp; -#endif +uniform int omni_light_indices[MAX_FORWARD_LIGHTS]; +uniform int omni_light_count; -#if defined(ENABLE_COLOR_INTERP) -in vec4 color_interp; -#endif +uniform int spot_light_indices[MAX_FORWARD_LIGHTS]; +uniform int spot_light_count; -#if defined(ENABLE_UV_INTERP) -in vec2 uv_interp; -#endif +uniform int reflection_indices[MAX_FORWARD_LIGHTS]; +uniform int reflection_count; -#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) -in vec2 uv2_interp;  #endif -in vec3 view_interp; +uniform highp sampler2D screen_texture; // texunit:-5 +uniform highp sampler2D depth_buffer; // texunit:-6  layout(location = 0) out vec4 frag_color; +in highp vec4 position_interp; +  vec3 F0(float metallic, float specular, vec3 albedo) {  	float dielectric = 0.16 * specular * specular;  	// use albedo * metallic as colored specular reflectance at 0 angle for metallic materials; @@ -985,95 +538,31 @@ vec3 F0(float metallic, float specular, vec3 albedo) {  	return mix(vec3(dielectric), albedo, vec3(metallic));  } -/* clang-format off */ - -FRAGMENT_SHADER_GLOBALS - -/* clang-format on */ - -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - -in highp float dp_clip; - -#endif - -#ifdef USE_LIGHTING - -// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V. -// We're dividing this factor off because the overall term we'll end up looks like -// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012): -// -//   F(L.V) D(N.H) G(N.L) G(N.V) / (4 N.L N.V) -// -// We're basically regouping this as -// -//   F(L.V) D(N.H) [G(N.L)/(2 N.L)] [G(N.V) / (2 N.V)] -// -// and thus, this function implements the [G(N.m)/(2 N.m)] part with m = L or V. -// -// The contents of the D and G (G1) functions (GGX) are taken from -// E. Heitz, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs", J. Comp. Graph. Tech. 3 (2) (2014). -// Eqns 71-72 and 85-86 (see also Eqns 43 and 80). - -/* -float G_GGX_2cos(float cos_theta_m, float alpha) { -	// Schlick's approximation -	// C. Schlick, "An Inexpensive BRDF Model for Physically-based Rendering", Computer Graphics Forum. 13 (3): 233 (1994) -	// Eq. (19), although see Heitz (2014) the about the problems with his derivation. -	// It nevertheless approximates GGX well with k = alpha/2. -	float k = 0.5 * alpha; -	return 0.5 / (cos_theta_m * (1.0 - k) + k); - -	// float cos2 = cos_theta_m * cos_theta_m; -	// float sin2 = (1.0 - cos2); -	// return 1.0 / (cos_theta_m + sqrt(cos2 + alpha * alpha * sin2)); -} -*/ - -// This approximates G_GGX_2cos(cos_theta_l, alpha) * G_GGX_2cos(cos_theta_v, alpha) -// See Filament docs, Specular G section. -float V_GGX(float cos_theta_l, float cos_theta_v, float alpha) { -	return 0.5 / mix(2.0 * cos_theta_l * cos_theta_v, cos_theta_l + cos_theta_v, alpha); -} - +#if defined(USE_LIGHT_DIRECTIONAL) || defined(USE_LIGHT_POSITIONAL)  float D_GGX(float cos_theta_m, float alpha) { -	float alpha2 = alpha * alpha; -	float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m; -	return alpha2 / (M_PI * d * d); -} - -/* -float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { -	float cos2 = cos_theta_m * cos_theta_m; -	float sin2 = (1.0 - cos2); -	float s_x = alpha_x * cos_phi; -	float s_y = alpha_y * sin_phi; -	return 1.0 / max(cos_theta_m + sqrt(cos2 + (s_x * s_x + s_y * s_y) * sin2), 0.001); +	float a = cos_theta_m * alpha; +	float k = alpha / (1.0 - cos_theta_m * cos_theta_m + a * a); +	return k * k * (1.0 / M_PI);  } -*/ -// This approximates G_GGX_anisotropic_2cos(cos_theta_l, ...) * G_GGX_anisotropic_2cos(cos_theta_v, ...) -// See Filament docs, Anisotropic specular BRDF section. -float V_GGX_anisotropic(float alpha_x, float alpha_y, float TdotV, float TdotL, float BdotV, float BdotL, float NdotV, float NdotL) { -	float Lambda_V = NdotL * length(vec3(alpha_x * TdotV, alpha_y * BdotV, NdotV)); -	float Lambda_L = NdotV * length(vec3(alpha_x * TdotL, alpha_y * BdotL, NdotL)); -	return 0.5 / (Lambda_V + Lambda_L); +// From Earl Hammon, Jr. "PBR Diffuse Lighting for GGX+Smith Microsurfaces" https://www.gdcvault.com/play/1024478/PBR-Diffuse-Lighting-for-GGX +float V_GGX(float NdotL, float NdotV, float alpha) { +	return 0.5 / mix(2.0 * NdotL * NdotV, NdotL + NdotV, alpha);  } -float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi, float NdotH) { +float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) {  	float alpha2 = alpha_x * alpha_y; -	highp vec3 v = vec3(alpha_y * cos_phi, alpha_x * sin_phi, alpha2 * NdotH); +	highp vec3 v = vec3(alpha_y * cos_phi, alpha_x * sin_phi, alpha2 * cos_theta_m);  	highp float v2 = dot(v, v);  	float w2 = alpha2 / v2;  	float D = alpha2 * w2 * w2 * (1.0 / M_PI);  	return D; +} -	/* float cos2 = cos_theta_m * cos_theta_m; -	float sin2 = (1.0 - cos2); -	float r_x = cos_phi / alpha_x; -	float r_y = sin_phi / alpha_y; -	float d = cos2 + sin2 * (r_x * r_x + r_y * r_y); -	return 1.0 / max(M_PI * alpha_x * alpha_y * d * d, 0.001); */ +float V_GGX_anisotropic(float alpha_x, float alpha_y, float TdotV, float TdotL, float BdotV, float BdotL, float NdotV, float NdotL) { +	float Lambda_V = NdotL * length(vec3(alpha_x * TdotV, alpha_y * BdotV, NdotV)); +	float Lambda_L = NdotV * length(vec3(alpha_x * TdotL, alpha_y * BdotL, NdotL)); +	return 0.5 / (Lambda_V + Lambda_L);  }  float SchlickFresnel(float u) { @@ -1082,109 +571,64 @@ float SchlickFresnel(float u) {  	return m2 * m2 * m; // pow(m,5)  } -float GTR1(float NdotH, float a) { -	if (a >= 1.0) -		return 1.0 / M_PI; -	float a2 = a * a; -	float t = 1.0 + (a2 - 1.0) * NdotH * NdotH; -	return (a2 - 1.0) / (M_PI * log(a2) * t); -} +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, +#ifdef LIGHT_BACKLIGHT_USED +		vec3 backlight, +#endif +#ifdef LIGHT_RIM_USED +		float rim, float rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED +		float clearcoat, float clearcoat_roughness, vec3 vertex_normal, +#endif +#ifdef LIGHT_ANISOTROPY_USED +		vec3 B, vec3 T, float anisotropy, +#endif +		inout vec3 diffuse_light, inout vec3 specular_light) { -void light_compute( -		vec3 N, -		vec3 L, -		vec3 V, -		vec3 B, -		vec3 T, -		vec3 light_color, -		vec3 attenuation, -		vec3 diffuse_color, -		vec3 transmission, -		float specular_blob_intensity, -		float roughness, -		float metallic, -		float specular, -		float rim, -		float rim_tint, -		float clearcoat, -		float clearcoat_roughness, -		float anisotropy, -		inout vec3 diffuse_light, -		inout vec3 specular_light, -		inout float alpha) { -//this makes lights behave closer to linear, but then addition of lights looks bad -//better left disabled +	vec4 orms_unpacked = unpackUnorm4x8(orms); -//#define SRGB_APPROX(m_var) m_var = pow(m_var,0.4545454545); -/* -#define SRGB_APPROX(m_var) {\ -	float S1 = sqrt(m_var);\ -	float S2 = sqrt(S1);\ -	float S3 = sqrt(S2);\ -	m_var = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.0225411470 * m_var;\ -	} -*/ -#define SRGB_APPROX(m_var) +	float roughness = orms_unpacked.y; +	float metallic = orms_unpacked.z;  #if defined(USE_LIGHT_SHADER_CODE)  	// light is written by the light shader  	vec3 normal = N; -	vec3 albedo = diffuse_color;  	vec3 light = L;  	vec3 view = V;  	/* clang-format off */ -LIGHT_SHADER_CODE + +#CODE : LIGHT  	/* clang-format on */  #else -	float NdotL = dot(N, L); +	float NdotL = min(A + dot(N, L), 1.0);  	float cNdotL = max(NdotL, 0.0); // clamped NdotL  	float NdotV = dot(N, V); -	float cNdotV = max(abs(NdotV), 1e-6); +	float cNdotV = max(NdotV, 0.0); -#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)  	vec3 H = normalize(V + L);  #endif -#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) -	float cNdotH = max(dot(N, H), 0.0); +#if defined(SPECULAR_SCHLICK_GGX) +	float cNdotH = clamp(A + dot(N, H), 0.0, 1.0);  #endif -#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) -	float cLdotH = max(dot(L, H), 0.0); +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) +	float cLdotH = clamp(A + dot(L, H), 0.0, 1.0);  #endif  	if (metallic < 1.0) { -#if defined(DIFFUSE_OREN_NAYAR) -		vec3 diffuse_brdf_NL; -#else  		float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance -#endif  #if defined(DIFFUSE_LAMBERT_WRAP)  		// energy conserving lambert wrap shader  		diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); - -#elif defined(DIFFUSE_OREN_NAYAR) - -		{ -			// see http://mimosa-pudica.net/improved-oren-nayar.html -			float LdotV = dot(L, V); - -			float s = LdotV - NdotL * NdotV; -			float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); - -			float sigma2 = roughness * roughness; // TODO: this needs checking -			vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13)); -			float B = 0.45 * sigma2 / (sigma2 + 0.09); - -			diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); -		} -  #elif defined(DIFFUSE_TOON)  		diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL); @@ -1196,230 +640,208 @@ LIGHT_SHADER_CODE  			float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV);  			float FdL = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotL);  			diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL; -			/* -			float energyBias = mix(roughness, 0.0, 0.5); -			float energyFactor = mix(roughness, 1.0, 1.0 / 1.51); -			float fd90 = energyBias + 2.0 * VoH * VoH * roughness; -			float f0 = 1.0; -			float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0); -			float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0); - -			diffuse_brdf_NL = lightScatter * viewScatter * energyFactor; -			*/  		}  #else  		// lambert  		diffuse_brdf_NL = cNdotL * (1.0 / M_PI);  #endif -		SRGB_APPROX(diffuse_brdf_NL) - -		diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation; +		diffuse_light += light_color * diffuse_brdf_NL * attenuation; -#if defined(TRANSMISSION_USED) -		diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation; +#if defined(LIGHT_BACKLIGHT_USED) +		diffuse_light += light_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;  #endif -#if defined(LIGHT_USE_RIM) +#if defined(LIGHT_RIM_USED)  		float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0)); -		diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color; +		diffuse_light += rim_light * rim * mix(vec3(1.0), albedo, rim_tint) * light_color;  #endif  	} -	if (roughness > 0.0) { - -#if defined(SPECULAR_SCHLICK_GGX) -		vec3 specular_brdf_NL = vec3(0.0); -#else -		float specular_brdf_NL = 0.0; -#endif +	if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely -#if defined(SPECULAR_BLINN) - -		//normalized blinn -		float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; -		float blinn = pow(cNdotH, shininess) * cNdotL; -		blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); -		specular_brdf_NL = blinn; - -#elif defined(SPECULAR_PHONG) - -		vec3 R = normalize(-reflect(L, N)); -		float cRdotV = max(0.0, dot(R, V)); -		float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; -		float phong = pow(cRdotV, shininess); -		phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); -		specular_brdf_NL = (phong) / max(4.0 * cNdotV * cNdotL, 0.75); +		// D -#elif defined(SPECULAR_TOON) +#if defined(SPECULAR_TOON)  		vec3 R = normalize(-reflect(L, N));  		float RdotV = dot(R, V);  		float mid = 1.0 - roughness;  		mid *= mid; -		specular_brdf_NL = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid; +		float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid; +		diffuse_light += light_color * intensity * attenuation * specular_amount; // write to diffuse_light, as in toon shading you generally want no reflection  #elif defined(SPECULAR_DISABLED)  		// none.. +  #elif defined(SPECULAR_SCHLICK_GGX)  		// shlick+ggx as default - -#if defined(LIGHT_USE_ANISOTROPY)  		float alpha_ggx = roughness * roughness; +#if defined(LIGHT_ANISOTROPY_USED) +  		float aspect = sqrt(1.0 - anisotropy * 0.9);  		float ax = alpha_ggx / aspect;  		float ay = alpha_ggx * aspect;  		float XdotH = dot(T, H);  		float YdotH = dot(B, H); -		float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH, cNdotH); -		//float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH); +		float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH);  		float G = V_GGX_anisotropic(ax, ay, dot(T, V), dot(T, L), dot(B, V), dot(B, L), cNdotV, cNdotL); - -#else -		float alpha_ggx = roughness * roughness; +#else // LIGHT_ANISOTROPY_USED  		float D = D_GGX(cNdotH, alpha_ggx); -		//float G = G_GGX_2cos(cNdotL, alpha_ggx) * G_GGX_2cos(cNdotV, alpha_ggx);  		float G = V_GGX(cNdotL, cNdotV, alpha_ggx); -#endif -		// F -		vec3 f0 = F0(metallic, specular, diffuse_color); +#endif // LIGHT_ANISOTROPY_USED +	   // F  		float cLdotH5 = SchlickFresnel(cLdotH);  		vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); -		specular_brdf_NL = cNdotL * D * F * G; +		vec3 specular_brdf_NL = cNdotL * D * F * G; +		specular_light += specular_brdf_NL * light_color * attenuation * specular_amount;  #endif -		SRGB_APPROX(specular_brdf_NL) -		specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; - -#if defined(LIGHT_USE_CLEARCOAT) +#if defined(LIGHT_CLEARCOAT_USED) +		// Clearcoat ignores normal_map, use vertex normal instead +		float ccNdotL = max(min(A + dot(vertex_normal, L), 1.0), 0.0); +		float ccNdotH = clamp(A + dot(vertex_normal, H), 0.0, 1.0); +		float ccNdotV = max(dot(vertex_normal, V), 1e-4);  #if !defined(SPECULAR_SCHLICK_GGX)  		float cLdotH5 = SchlickFresnel(cLdotH);  #endif -		float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_roughness)); +		float Dr = D_GGX(ccNdotH, mix(0.001, 0.1, clearcoat_roughness)); +		float Gr = 0.25 / (cLdotH * cLdotH);  		float Fr = mix(.04, 1.0, cLdotH5); -		//float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); -		float Gr = V_GGX(cNdotL, cNdotV, 0.25); - -		float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; +		float clearcoat_specular_brdf_NL = clearcoat * Gr * Fr * Dr * cNdotL; -		specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation; -#endif +		specular_light += clearcoat_specular_brdf_NL * light_color * attenuation * specular_amount; +		// TODO: Clearcoat adds light to the scene right now (it is non-energy conserving), both diffuse and specular need to be scaled by (1.0 - FR) +		// but to do so we need to rearrange this entire function +#endif // LIGHT_CLEARCOAT_USED  	}  #ifdef USE_SHADOW_TO_OPACITY -	alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0)); +	alpha = min(alpha, clamp(1.0 - attenuation, 0.0, 1.0));  #endif -#endif //defined(USE_LIGHT_SHADER_CODE) +#endif //defined(LIGHT_CODE_USED)  } -#endif -// shadows - -#ifdef USE_SHADOW - -#ifdef USE_RGBA_SHADOWS - -#define SHADOW_DEPTH(m_val) dot(m_val, 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_val) (m_val).r +float get_omni_attenuation(float distance, float inv_range, float decay) { +	float nd = distance * inv_range; +	nd *= nd; +	nd *= nd; // nd^4 +	nd = max(1.0 - nd, 0.0); +	nd *= nd; // nd^2 +	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, +#ifdef LIGHT_BACKLIGHT_USED +		vec3 backlight,  #endif - -#define SAMPLE_SHADOW_TEXEL(p_shadow, p_pos, p_depth) step(p_depth, SHADOW_DEPTH(texture(p_shadow, p_pos))) -#define SAMPLE_SHADOW_TEXEL_PROJ(p_shadow, p_pos) step(p_pos.z, SHADOW_DEPTH(textureProj(p_shadow, p_pos))) - -float sample_shadow(highp sampler2D shadow, highp vec4 spos) { -#ifdef SHADOW_MODE_PCF_13 - -	spos.xyz /= spos.w; -	vec2 pos = spos.xy; -	float depth = spos.z; - -	float avg = SAMPLE_SHADOW_TEXEL(shadow, pos, depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, 0.0), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, 0.0), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth); -	return avg * (1.0 / 13.0); +#ifdef LIGHT_TRANSMITTANCE_USED +		vec4 transmittance_color, +		float transmittance_depth, +		float transmittance_boost,  #endif - -#ifdef SHADOW_MODE_PCF_5 - -	spos.xyz /= spos.w; -	vec2 pos = spos.xy; -	float depth = spos.z; - -	float avg = SAMPLE_SHADOW_TEXEL(shadow, pos, depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, 0.0), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, 0.0), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y), depth); -	avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y), depth); -	return avg * (1.0 / 5.0); - +#ifdef LIGHT_RIM_USED +		float rim, float rim_tint,  #endif +#ifdef LIGHT_CLEARCOAT_USED +		float clearcoat, float clearcoat_roughness, vec3 vertex_normal, +#endif +#ifdef LIGHT_ANISOTROPY_USED +		vec3 binormal, vec3 tangent, float anisotropy, +#endif +		inout vec3 diffuse_light, inout vec3 specular_light) { +	vec3 light_rel_vec = omni_lights[idx].position - vertex; +	float light_length = length(light_rel_vec); +	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; +	float size_A = 0.0; + +	if (omni_lights.data[idx].size > 0.0) { +		float t = omni_lights[idx].size / max(0.001, light_length); +		size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); +	} -#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13) - -	return SAMPLE_SHADOW_TEXEL_PROJ(shadow, spos); +	light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights[idx].specular_amount, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED +			backlight, +#endif +#ifdef LIGHT_RIM_USED +			rim * omni_attenuation, rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED +			clearcoat, clearcoat_roughness, vertex_normal,  #endif +#ifdef LIGHT_ANISOTROPY_USED +			binormal, tangent, anisotropy, +#endif +			diffuse_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, +#ifdef LIGHT_BACKLIGHT_USED +		vec3 backlight,  #endif - -#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - -#if defined(USE_VERTEX_LIGHTING) - -in vec4 fog_interp; - -#else -uniform mediump vec4 fog_color_base; -#ifdef LIGHT_MODE_DIRECTIONAL -uniform mediump vec4 fog_sun_color_amount; +#ifdef LIGHT_RIM_USED +		float rim, float rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED +		float clearcoat, float clearcoat_roughness, vec3 vertex_normal,  #endif +#ifdef LIGHT_ANISOTROPY_USED +		vec3 binormal, vec3 tangent, float anisotropy, +#endif +		inout vec3 diffuse_light, +		inout vec3 specular_light) { -uniform bool fog_transmit_enabled; -uniform mediump float fog_transmit_curve; +	vec3 light_rel_vec = spot_lights[idx].position - vertex; +	float light_length = length(light_rel_vec); +	float spot_attenuation = get_omni_attenuation(light_length, spot_lights[idx].inv_radius, spot_lights[idx].attenuation); +	vec3 spot_dir = spot_lights[idx].direction; +	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)); +	spot_attenuation *= 1.0 - pow(spot_rim, spot_lights[idx].cone_attenuation); +	float light_attenuation = spot_attenuation; +	vec3 color = spot_lights[idx].color; + +	float size_A = 0.0; + +	if (spot_lights.data[idx].size > 0.0) { +		float t = spot_lights.data[idx].size / max(0.001, light_length); +		size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); +	} -#ifdef FOG_DEPTH_ENABLED -uniform highp float fog_depth_begin; -uniform mediump float fog_depth_curve; -uniform mediump float fog_max_distance; +	light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights[idx].specular_amount, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED +			backlight,  #endif - -#ifdef FOG_HEIGHT_ENABLED -uniform highp float fog_height_min; -uniform highp float fog_height_max; -uniform mediump float fog_height_curve; +#ifdef LIGHT_RIM_USED +			rim * spot_attenuation, rim_tint,  #endif - -#endif //vertex lit -#endif //fog +#ifdef LIGHT_CLEARCOAT_USED +			clearcoat, clearcoat_roughness, vertex_normal, +#endif +#ifdef LIGHT_ANISOTROPY_USED +			binormal, tangent, anisotropy, +#endif +			diffuse_light, specular_light); +} +#endif // defined(USE_LIGHT_DIRECTIONAL) || defined(USE_LIGHT_POSITIONAL)  void main() { -#ifdef RENDER_DEPTH_DUAL_PARABOLOID - -	if (dp_clip > 0.0) -		discard; -#endif -	highp vec3 vertex = vertex_interp; +	//lay out everything, whatever is unused is optimized away anyway +	vec3 vertex = vertex_interp;  	vec3 view = -normalize(vertex_interp);  	vec3 albedo = vec3(1.0); -	vec3 transmission = vec3(0.0); +	vec3 backlight = vec3(0.0); +	vec4 transmittance_color = vec4(0.0, 0.0, 0.0, 1.0); +	float transmittance_depth = 0.0; +	float transmittance_boost = 0.0;  	float metallic = 0.0;  	float specular = 0.5;  	vec3 emission = vec3(0.0); @@ -1430,617 +852,235 @@ void main() {  	float clearcoat_roughness = 0.0;  	float anisotropy = 0.0;  	vec2 anisotropy_flow = vec2(1.0, 0.0); -	float sss_strength = 0.0; //unused -	// gl_FragDepth is not available in GLES2, so writing to DEPTH is not converted to gl_FragDepth by Godot compiler resulting in a -	// compile error because DEPTH is not a variable. -	float m_DEPTH = 0.0; - -	float alpha = 1.0; -	float side = 1.0; - -	float specular_blob_intensity = 1.0; -#if defined(SPECULAR_TOON) -	specular_blob_intensity *= specular * 2.0; +	vec4 fog = vec4(0.0); +#if defined(CUSTOM_RADIANCE_USED) +	vec4 custom_radiance = vec4(0.0); +#endif +#if defined(CUSTOM_IRRADIANCE_USED) +	vec4 custom_irradiance = vec4(0.0);  #endif -#if defined(ENABLE_AO)  	float ao = 1.0;  	float ao_light_affect = 0.0; -#endif -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) -	vec3 binormal = normalize(binormal_interp) * side; -	vec3 tangent = normalize(tangent_interp) * side; +	float alpha = 1.0; + +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) +	vec3 binormal = normalize(binormal_interp); +	vec3 tangent = normalize(tangent_interp);  #else  	vec3 binormal = vec3(0.0);  	vec3 tangent = vec3(0.0);  #endif -	vec3 normal = normalize(normal_interp) * side; -#if defined(ENABLE_NORMALMAP) -	vec3 normalmap = vec3(0.5); +#ifdef NORMAL_USED +	vec3 normal = normalize(normal_interp); + +#if defined(DO_SIDE_CHECK) +	if (!gl_FrontFacing) { +		normal = -normal; +	}  #endif -	float normaldepth = 1.0; -#if defined(ALPHA_SCISSOR_USED) -	float alpha_scissor = 0.5; +#endif //NORMAL_USED + +#ifdef UV_USED +	vec2 uv = uv_interp;  #endif -#if defined(SCREEN_UV_USED) -	vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; +#if defined(UV2_USED) || defined(USE_LIGHTMAP) +	vec2 uv2 = uv2_interp;  #endif -	{ -		/* clang-format off */ +#if defined(COLOR_USED) +	vec4 color = color_interp; +#endif -FRAGMENT_SHADER_CODE +#if defined(NORMAL_MAP_USED) -		/* clang-format on */ -	} +	vec3 normal_map = vec3(0.5); +#endif -#if defined(ENABLE_NORMALMAP) -	normalmap.xy = normalmap.xy * 2.0 - 1.0; -	normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); +	float normal_map_depth = 1.0; -	normal = normalize(mix(normal_interp, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)) * side; -	//normal = normalmap; -#endif +	vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center -	normal = normalize(normal); +	float sss_strength = 0.0; -	vec3 N = normal; +#ifdef ALPHA_SCISSOR_USED +	float alpha_scissor_threshold = 1.0; +#endif // ALPHA_SCISSOR_USED -	vec3 specular_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); +#ifdef ALPHA_HASH_USED +	float alpha_hash_scale = 1.0; +#endif // ALPHA_HASH_USED -	vec3 eye_position = view; +#ifdef ALPHA_ANTIALIASING_EDGE_USED +	float alpha_antialiasing_edge = 0.0; +	vec2 alpha_texture_coordinate = vec2(0.0, 0.0); +#endif // ALPHA_ANTIALIASING_EDGE_USED +	{ +#CODE : FRAGMENT +	} -#if !defined(USE_SHADOW_TO_OPACITY) +#ifndef USE_SHADOW_TO_OPACITY  #if defined(ALPHA_SCISSOR_USED) -	if (alpha < alpha_scissor) { +	if (alpha < alpha_scissor_threshold) {  		discard;  	}  #endif // ALPHA_SCISSOR_USED -#ifdef USE_DEPTH_PREPASS -	if (alpha < 0.1) { +#ifdef USE_OPAQUE_PREPASS +#if !defined(ALPHA_SCISSOR_USED) + +	if (alpha < scene_data.opaque_prepass_threshold) {  		discard;  	} -#endif // USE_DEPTH_PREPASS -#endif // !USE_SHADOW_TO_OPACITY +#endif // not ALPHA_SCISSOR_USED +#endif // USE_OPAQUE_PREPASS -#ifdef BASE_PASS - -	// IBL precalculations -	float ndotv = clamp(dot(normal, eye_position), 0.0, 1.0); -	vec3 f0 = F0(metallic, specular, albedo); -	vec3 F = f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - ndotv, 5.0); - -#ifdef AMBIENT_LIGHT_DISABLED -	ambient_light = vec3(0.0, 0.0, 0.0); -#else - -#ifdef USE_RADIANCE_MAP - -	vec3 ref_vec = reflect(-eye_position, N); -	ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz); - -	ref_vec.z *= -1.0; - -	specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy; -#ifndef USE_LIGHTMAP -	{ -		vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz); -		vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, 4.0).xyz * bg_energy; -		env_ambient *= 1.0 - F; +#endif // !USE_SHADOW_TO_OPACITY -		ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution); -	} -#endif +#ifdef NORMAL_MAP_USED -#else +	normal_map.xy = normal_map.xy * 2.0 - 1.0; +	normal_map.z = sqrt(max(0.0, 1.0 - dot(normal_map.xy, normal_map.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. -	ambient_light = ambient_color.rgb; -	specular_light = bg_color.rgb * bg_energy; +	normal = normalize(mix(normal, tangent * normal_map.x + binormal * normal_map.y + normal * normal_map.z, normal_map_depth));  #endif -#endif // AMBIENT_LIGHT_DISABLED -	ambient_light *= ambient_energy; - -#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) -	vec4 ambient_accum = vec4(0.0); -	vec4 reflection_accum = vec4(0.0); +#ifdef LIGHT_ANISOTROPY_USED -#ifdef USE_REFLECTION_PROBE1 +	if (anisotropy > 0.01) { +		//rotation matrix +		mat3 rot = mat3(tangent, binormal, normal); +		//make local to space +		tangent = normalize(rot * vec3(anisotropy_flow.x, anisotropy_flow.y, 0.0)); +		binormal = normalize(rot * vec3(-anisotropy_flow.y, anisotropy_flow.x, 0.0)); +	} -	reflection_process(reflection_probe1, -#ifdef USE_VERTEX_LIGHTING -			refprobe1_reflection_normal_blend.rgb, -#ifndef USE_LIGHTMAP -			refprobe1_ambient_normal,  #endif -			refprobe1_reflection_normal_blend.a, -#else -			normal_interp, vertex_interp, refprobe1_local_matrix, -			refprobe1_use_box_project, refprobe1_box_extents, refprobe1_box_offset, -#endif -			refprobe1_exterior, refprobe1_intensity, refprobe1_ambient, roughness, -			ambient_light, specular_light, reflection_accum, ambient_accum); -#endif // USE_REFLECTION_PROBE1 +#ifndef MODE_RENDER_DEPTH +	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 diffuse_light = vec3(0.0, 0.0, 0.0); +	vec3 ambient_light = vec3(0.0, 0.0, 0.0); -#ifdef USE_REFLECTION_PROBE2 +#ifdef BASE_PASS +	/////////////////////// LIGHTING ////////////////////////////// -	reflection_process(reflection_probe2, -#ifdef USE_VERTEX_LIGHTING -			refprobe2_reflection_normal_blend.rgb, -#ifndef USE_LIGHTMAP -			refprobe2_ambient_normal, -#endif -			refprobe2_reflection_normal_blend.a, -#else -			normal_interp, vertex_interp, refprobe2_local_matrix, -			refprobe2_use_box_project, refprobe2_box_extents, refprobe2_box_offset, -#endif -			refprobe2_exterior, refprobe2_intensity, refprobe2_ambient, roughness, -			ambient_light, specular_light, reflection_accum, ambient_accum); +	// IBL precalculations +	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); -#endif // USE_REFLECTION_PROBE2 +	// Calculate IBL +	// Calculate Reflection probes +	// Caclculate Lightmaps -	if (reflection_accum.a > 0.0) { -		specular_light = reflection_accum.rgb / reflection_accum.a; -	} +	float specular_blob_intensity = 1.0; -#ifndef USE_LIGHTMAP -	if (ambient_accum.a > 0.0) { -		ambient_light = ambient_accum.rgb / ambient_accum.a; -	} +#if defined(SPECULAR_TOON) +	specular_blob_intensity *= specular * 2.0;  #endif -#endif // defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) - -	// environment BRDF approximation  	{  #if defined(DIFFUSE_TOON)  		//simplify for toon, as  		specular_light *= specular * metallic * albedo * 2.0;  #else -		// scales the specular reflections, needs to be computed before lighting happens, -		// but after environment and reflection probes are added -		//TODO: this curve is not really designed for gammaspace, should be adjusted +		// scales the specular reflections, needs to be be computed before lighting happens, +		// but after environment, GI, and reflection probes are added +		// Environment brdf approximation (Lazarov 2013) +		// see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile  		const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);  		const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);  		vec4 r = roughness * c0 + c1; +		float ndotv = clamp(dot(normal, view), 0.0, 1.0); +  		float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;  		vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; -		specular_light *= env.x * F + env.y; - +		specular_light *= env.x * f0 + env.y;  #endif  	} -#ifdef USE_LIGHTMAP -	//ambient light will come entirely from lightmap is lightmap is used -	ambient_light = texture(lightmap, uv2_interp).rgb * lightmap_energy; -#endif - -#ifdef USE_LIGHTMAP_CAPTURE -	{ -		vec3 cone_dirs[12]; -		cone_dirs[0] = vec3(0.0, 0.0, 1.0); -		cone_dirs[1] = vec3(0.866025, 0.0, 0.5); -		cone_dirs[2] = vec3(0.267617, 0.823639, 0.5); -		cone_dirs[3] = vec3(-0.700629, 0.509037, 0.5); -		cone_dirs[4] = vec3(-0.700629, -0.509037, 0.5); -		cone_dirs[5] = vec3(0.267617, -0.823639, 0.5); -		cone_dirs[6] = vec3(0.0, 0.0, -1.0); -		cone_dirs[7] = vec3(0.866025, 0.0, -0.5); -		cone_dirs[8] = vec3(0.267617, 0.823639, -0.5); -		cone_dirs[9] = vec3(-0.700629, 0.509037, -0.5); -		cone_dirs[10] = vec3(-0.700629, -0.509037, -0.5); -		cone_dirs[11] = vec3(0.267617, -0.823639, -0.5); - -		vec3 local_normal = normalize(inv_view_matrix * vec4(normal, 0.0)).xyz; -		vec4 captured = vec4(0.0); -		float sum = 0.0; -		for (int i = 0; i < 12; i++) { -			float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect -			captured += lightmap_captures[i] * amount; -			sum += amount; -		} - -		captured /= sum; - -		if (lightmap_capture_sky) { -			ambient_light = mix(ambient_light, captured.rgb, captured.a); -		} else { -			ambient_light = captured.rgb; -		} -	} -#endif - -#endif //BASE PASS - -// -// Lighting -// -#ifdef USE_LIGHTING - -#ifndef USE_VERTEX_LIGHTING -	vec3 L; -#endif -	vec3 light_att = vec3(1.0); - -#ifdef LIGHT_MODE_OMNI - -#ifndef USE_VERTEX_LIGHTING -	vec3 light_vec = light_position - vertex; -	float light_length = length(light_vec); - -	float normalized_distance = light_length / light_range; -	if (normalized_distance < 1.0) { -		float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation); - -		light_att = vec3(omni_attenuation); -	} else { -		light_att = vec3(0.0); -	} -	L = normalize(light_vec); - -#endif - -#if !defined(SHADOWS_DISABLED) - -#ifdef USE_SHADOW -	{ -		highp vec4 splane = shadow_coord; -		float shadow_len = length(splane.xyz); - -		splane.xyz = normalize(splane.xyz); - -		vec4 clamp_rect = light_clamp; - -		if (splane.z >= 0.0) { -			splane.z += 1.0; - -			clamp_rect.y += clamp_rect.w; -		} else { -			splane.z = 1.0 - splane.z; -		} - -		splane.xy /= splane.z; -		splane.xy = splane.xy * 0.5 + 0.5; -		splane.z = shadow_len / light_range; - -		splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw; -		splane.w = 1.0; - -		float shadow = sample_shadow(light_shadow_atlas, splane); - -		light_att *= mix(shadow_color.rgb, vec3(1.0), shadow); -	} -#endif - -#endif //SHADOWS_DISABLED - -#endif //type omni - -#ifdef LIGHT_MODE_DIRECTIONAL - -#ifndef USE_VERTEX_LIGHTING -	vec3 light_vec = -light_direction; -	L = normalize(light_vec); -#endif -	float depth_z = -vertex.z; - -#if !defined(SHADOWS_DISABLED) +#endif // BASE_PASS -#ifdef USE_SHADOW +	//this saves some VGPRs +	uint orms = packUnorm4x8(vec4(ao, roughness, metallic, specular)); -#ifdef USE_VERTEX_LIGHTING -	//compute shadows in a mobile friendly way +#ifdef USE_LIGHT_DIRECTIONAL -#ifdef LIGHT_USE_PSSM4 -	//take advantage of prefetch -	float shadow1 = sample_shadow(light_directional_shadow, shadow_coord); -	float shadow2 = sample_shadow(light_directional_shadow, shadow_coord2); -	float shadow3 = sample_shadow(light_directional_shadow, shadow_coord3); -	float shadow4 = sample_shadow(light_directional_shadow, shadow_coord4); +	float size_A = directional_lights[i].size; -	if (depth_z < light_split_offsets.w) { -		float pssm_fade = 0.0; -		float shadow_att = 1.0; -#ifdef LIGHT_USE_PSSM_BLEND -		float shadow_att2 = 1.0; -		float pssm_blend = 0.0; -		bool use_blend = true; +	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 +			backlight,  #endif -		if (depth_z < light_split_offsets.y) { -			if (depth_z < light_split_offsets.x) { -				shadow_att = shadow1; - -#ifdef LIGHT_USE_PSSM_BLEND -				shadow_att2 = shadow2; - -				pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); +#ifdef LIGHT_RIM_USED +			rim, rim_tint,  #endif -			} else { -				shadow_att = shadow2; - -#ifdef LIGHT_USE_PSSM_BLEND -				shadow_att2 = shadow3; - -				pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); +#ifdef LIGHT_CLEARCOAT_USED +			clearcoat, clearcoat_roughness, normalize(normal_interp),  #endif -			} -		} else { -			if (depth_z < light_split_offsets.z) { -				shadow_att = shadow3; - -#if defined(LIGHT_USE_PSSM_BLEND) -				shadow_att2 = shadow4; -				pssm_blend = smoothstep(light_split_offsets.y, light_split_offsets.z, depth_z); -#endif - -			} else { -				shadow_att = shadow4; -				pssm_fade = smoothstep(light_split_offsets.z, light_split_offsets.w, depth_z); - -#if defined(LIGHT_USE_PSSM_BLEND) -				use_blend = false; -#endif -			} -		} -#if defined(LIGHT_USE_PSSM_BLEND) -		if (use_blend) { -			shadow_att = mix(shadow_att, shadow_att2, pssm_blend); -		} +#ifdef LIGHT_ANISOTROPY_USED +			binormal, +			tangent, anisotropy,  #endif -		light_att *= mix(shadow_color.rgb, vec3(1.0), shadow_att); -	} - -#endif //LIGHT_USE_PSSM4 - -#ifdef LIGHT_USE_PSSM2 - -	//take advantage of prefetch -	float shadow1 = sample_shadow(light_directional_shadow, shadow_coord); -	float shadow2 = sample_shadow(light_directional_shadow, shadow_coord2); +			diffuse_light, +			specular_light); -	if (depth_z < light_split_offsets.y) { -		float shadow_att = 1.0; -		float pssm_fade = 0.0; +#endif //#USE_LIGHT_DIRECTIONAL -#ifdef LIGHT_USE_PSSM_BLEND -		float shadow_att2 = 1.0; -		float pssm_blend = 0.0; -		bool use_blend = true; +#ifdef USE_LIGHT_POSITIONAL +	float shadow = 0.0; +	for (int i = 0; i < omni_light_count; i++) { +		light_process_omni(omni_light_indices[i], vertex, view, normal, f0, orms, shadow, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED +				backlight,  #endif -		if (depth_z < light_split_offsets.x) { -			float pssm_fade = 0.0; -			shadow_att = shadow1; - -#ifdef LIGHT_USE_PSSM_BLEND -			shadow_att2 = shadow2; -			pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); +#ifdef LIGHT_RIM_USED +				rim, +				rim_tint,  #endif -		} else { -			shadow_att = shadow2; -			pssm_fade = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); -#ifdef LIGHT_USE_PSSM_BLEND -			use_blend = false; +#ifdef LIGHT_CLEARCOAT_USED +				clearcoat, clearcoat_roughness, normalize(normal_interp),  #endif -		} -#ifdef LIGHT_USE_PSSM_BLEND -		if (use_blend) { -			shadow_att = mix(shadow_att, shadow_att2, pssm_blend); -		} +#ifdef LIGHT_ANISOTROPY_USED +				tangent, binormal, anisotropy,  #endif -		light_att *= mix(shadow_color.rgb, vec3(1.0), shadow_att); +				diffuse_light, specular_light);  	} -#endif //LIGHT_USE_PSSM2 - -#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) - -	light_att *= mix(shadow_color.rgb, vec3(1.0), sample_shadow(light_directional_shadow, shadow_coord)); -#endif //orthogonal - -#else //fragment version of pssm - -	{ -#ifdef LIGHT_USE_PSSM4 -		if (depth_z < light_split_offsets.w) { -#elif defined(LIGHT_USE_PSSM2) -		if (depth_z < light_split_offsets.y) { -#else -		if (depth_z < light_split_offsets.x) { -#endif //pssm2 - -			highp vec4 pssm_coord; -			float pssm_fade = 0.0; - -#ifdef LIGHT_USE_PSSM_BLEND -			float pssm_blend; -			highp vec4 pssm_coord2; -			bool use_blend = true; -#endif - -#ifdef LIGHT_USE_PSSM4 - -			if (depth_z < light_split_offsets.y) { -				if (depth_z < light_split_offsets.x) { -					pssm_coord = shadow_coord; - -#ifdef LIGHT_USE_PSSM_BLEND -					pssm_coord2 = shadow_coord2; - -					pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); -#endif -				} else { -					pssm_coord = shadow_coord2; - -#ifdef LIGHT_USE_PSSM_BLEND -					pssm_coord2 = shadow_coord3; - -					pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); -#endif -				} -			} else { -				if (depth_z < light_split_offsets.z) { -					pssm_coord = shadow_coord3; - -#if defined(LIGHT_USE_PSSM_BLEND) -					pssm_coord2 = shadow_coord4; -					pssm_blend = smoothstep(light_split_offsets.y, light_split_offsets.z, depth_z); +	for (int i = 0; i < spot_light_count; i++) { +		light_process_spot(spot_light_indices[i], vertex, view, normal, f0, orms, shadow, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED +				backlight,  #endif - -				} else { -					pssm_coord = shadow_coord4; -					pssm_fade = smoothstep(light_split_offsets.z, light_split_offsets.w, depth_z); - -#if defined(LIGHT_USE_PSSM_BLEND) -					use_blend = false; -#endif -				} -			} - -#endif // LIGHT_USE_PSSM4 - -#ifdef LIGHT_USE_PSSM2 -			if (depth_z < light_split_offsets.x) { -				pssm_coord = shadow_coord; - -#ifdef LIGHT_USE_PSSM_BLEND -				pssm_coord2 = shadow_coord2; -				pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); +#ifdef LIGHT_RIM_USED +				rim, +				rim_tint,  #endif -			} else { -				pssm_coord = shadow_coord2; -				pssm_fade = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); -#ifdef LIGHT_USE_PSSM_BLEND -				use_blend = false; +#ifdef LIGHT_CLEARCOAT_USED +				clearcoat, clearcoat_roughness, normalize(normal_interp),  #endif -			} - -#endif // LIGHT_USE_PSSM2 - -#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) -			{ -				pssm_coord = shadow_coord; -			} -#endif - -			float shadow = sample_shadow(light_directional_shadow, pssm_coord); - -#ifdef LIGHT_USE_PSSM_BLEND -			if (use_blend) { -				shadow = mix(shadow, sample_shadow(light_directional_shadow, pssm_coord2), pssm_blend); -			} +#ifdef LIGHT_ANISOTROPY_USED +				tangent, +				binormal, anisotropy,  #endif - -			light_att *= mix(shadow_color.rgb, vec3(1.0), shadow); -		} +				diffuse_light, specular_light);  	} -#endif //use vertex lighting - -#endif //use shadow - -#endif // SHADOWS_DISABLED - -#endif - -#ifdef LIGHT_MODE_SPOT - -	light_att = vec3(1.0); - -#ifndef USE_VERTEX_LIGHTING - -	vec3 light_rel_vec = light_position - vertex; -	float light_length = length(light_rel_vec); -	float normalized_distance = light_length / light_range; -	if (normalized_distance < 1.0) { -		float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation); -		vec3 spot_dir = light_direction; - -		float spot_cutoff = light_spot_angle; -		float angle = dot(-normalize(light_rel_vec), spot_dir); - -		if (angle > spot_cutoff) { -			float scos = max(angle, spot_cutoff); -			float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff)); -			spot_attenuation *= 1.0 - pow(spot_rim, light_spot_attenuation); - -			light_att = vec3(spot_attenuation); -		} else { -			light_att = vec3(0.0); -		} -	} else { -		light_att = vec3(0.0); -	} - -	L = normalize(light_rel_vec); - -#endif - -#if !defined(SHADOWS_DISABLED) - -#ifdef USE_SHADOW -	{ -		highp vec4 splane = shadow_coord; - -		float shadow = sample_shadow(light_shadow_atlas, splane); -		light_att *= mix(shadow_color.rgb, vec3(1.0), shadow); -	} -#endif - -#endif // SHADOWS_DISABLED - -#endif // LIGHT_MODE_SPOT - -#ifdef USE_VERTEX_LIGHTING -	//vertex lighting - -	specular_light += specular_interp * specular_blob_intensity * light_att; -	diffuse_light += diffuse_interp * albedo * light_att; - -#else -	//fragment lighting -	light_compute( -			normal, -			L, -			eye_position, -			binormal, -			tangent, -			light_color.xyz, -			light_att, -			albedo, -			transmission, -			specular_blob_intensity * light_specular, -			roughness, -			metallic, -			specular, -			rim, -			rim_tint, -			clearcoat, -			clearcoat_roughness, -			anisotropy, -			diffuse_light, -			specular_light, -			alpha); - -#endif //vertex lighting - -#endif //USE_LIGHTING -	//compute and merge - -#ifdef USE_SHADOW_TO_OPACITY +#endif // USE_LIGHT_POSITIONAL +#endif //!MODE_RENDER_DEPTH +#if defined(USE_SHADOW_TO_OPACITY)  	alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));  #if defined(ALPHA_SCISSOR_USED) @@ -2049,105 +1089,50 @@ FRAGMENT_SHADER_CODE  	}  #endif // ALPHA_SCISSOR_USED -#ifdef USE_DEPTH_PREPASS -	if (alpha < 0.1) { +#ifdef USE_OPAQUE_PREPASS +#if !defined(ALPHA_SCISSOR_USED) + +	if (alpha < opaque_prepass_threshold) {  		discard;  	} -#endif // USE_DEPTH_PREPASS -#endif // !USE_SHADOW_TO_OPACITY +#endif // not ALPHA_SCISSOR_USED +#endif // USE_OPAQUE_PREPASS -#ifndef RENDER_DEPTH +#endif // USE_SHADOW_TO_OPACITY -#ifdef SHADELESS +#ifdef MODE_RENDER_DEPTH +//nothing happens, so a tree-ssa optimizer will result in no fragment shader :) +#else // !MODE_RENDER_DEPTH -	frag_color = vec4(albedo, alpha); -#else - -	ambient_light *= albedo; - -#if defined(ENABLE_AO) -	ambient_light *= ao; -	ao_light_affect = mix(1.0, ao, ao_light_affect); -	specular_light *= ao_light_affect; -	diffuse_light *= ao_light_affect; -#endif +	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 +	frag_color = vec4(albedo, alpha); +#else  	frag_color = vec4(ambient_light + diffuse_light + specular_light, alpha); - -	//add emission if in base pass  #ifdef BASE_PASS  	frag_color.rgb += emission;  #endif -	// frag_color = vec4(normal, 1.0); - -//apply fog -#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - -#if defined(USE_VERTEX_LIGHTING) - -#if defined(BASE_PASS) -	frag_color.rgb = mix(frag_color.rgb, fog_interp.rgb, fog_interp.a); -#else -	frag_color.rgb *= (1.0 - fog_interp.a); -#endif // BASE_PASS - -#else //pixel based fog -	float fog_amount = 0.0; - -#ifdef LIGHT_MODE_DIRECTIONAL - -	vec3 fog_color = mix(fog_color_base.rgb, fog_sun_color_amount.rgb, fog_sun_color_amount.a * pow(max(dot(eye_position, light_direction), 0.0), 8.0)); -#else -	vec3 fog_color = fog_color_base.rgb; -#endif - -#ifdef FOG_DEPTH_ENABLED +#endif //MODE_UNSHADED -	{ -		float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex)); +	// Tonemap before writing as we are writing to an sRGB framebuffer +	frag_color.rgb *= exposure; +	frag_color.rgb = apply_tonemapping(frag_color.rgb, white); +	frag_color.rgb = linear_to_srgb(frag_color.rgb); -		fog_amount = pow(fog_z, fog_depth_curve) * fog_color_base.a; - -		if (fog_transmit_enabled) { -			vec3 total_light = frag_color.rgb; -			float transmit = pow(fog_z, fog_transmit_curve); -			fog_color = mix(max(total_light, fog_color), fog_color, transmit); -		} -	} +#ifdef USE_BCS +	frag_color.rgb = apply_bcs(frag_color.rgb, bcs);  #endif -#ifdef FOG_HEIGHT_ENABLED -	{ -		float y = (inv_view_matrix * vec4(vertex, 1.0)).y; -		fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve)); -	} +#ifdef USE_COLOR_CORRECTION +	frag_color.rgb = apply_color_correction(frag_color.rgb, color_correction);  #endif -#if defined(BASE_PASS) -	frag_color.rgb = mix(frag_color.rgb, fog_color, fog_amount); -#else -	frag_color.rgb *= (1.0 - fog_amount); -#endif // BASE_PASS - -#endif //use vertex lit - -#endif // defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) - -#endif //unshaded - -#else // not RENDER_DEPTH -//depth render -#ifdef USE_RGBA_SHADOWS - -	highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; // bias -	highp vec4 comp = fract(depth * vec4(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); -	frag_color = comp; - -#endif -#endif +#endif //!MODE_RENDER_DEPTH  } diff --git a/drivers/gles3/shaders/stdlib_inc.glsl b/drivers/gles3/shaders/stdlib_inc.glsl index 2eddf9d479..3d976e9ab8 100644 --- a/drivers/gles3/shaders/stdlib_inc.glsl +++ b/drivers/gles3/shaders/stdlib_inc.glsl @@ -1,5 +1,5 @@ -//TODO: only needed by GLES_OVER_GL +#ifdef USE_GLES_OVER_GL  uint float2half(uint f) {  	return ((f >> uint(16)) & uint(0x8000)) |  			((((f & uint(0x7f800000)) - uint(0x38000000)) >> uint(13)) & uint(0x7c00)) | @@ -56,3 +56,4 @@ 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)));  	return clamp((v - vec4(127.0)) * vec4(0.00787401574), vec4(-1.0), vec4(1.0));  } +#endif diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 0641b4e87b..a3111da28a 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -900,6 +900,42 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,  ///////////////////////////////////////////////////////////////////////////  // MaterialData +// Look up table to translate ShaderLanguage::DataType to GL_TEXTURE_* +static const GLenum target_from_type[ShaderLanguage::TYPE_MAX] = { +	GL_TEXTURE_2D, // TYPE_VOID, +	GL_TEXTURE_2D, // TYPE_BOOL, +	GL_TEXTURE_2D, // TYPE_BVEC2, +	GL_TEXTURE_2D, // TYPE_BVEC3, +	GL_TEXTURE_2D, // TYPE_BVEC4, +	GL_TEXTURE_2D, // TYPE_INT, +	GL_TEXTURE_2D, // TYPE_IVEC2, +	GL_TEXTURE_2D, // TYPE_IVEC3, +	GL_TEXTURE_2D, // TYPE_IVEC4, +	GL_TEXTURE_2D, // TYPE_UINT, +	GL_TEXTURE_2D, // TYPE_UVEC2, +	GL_TEXTURE_2D, // TYPE_UVEC3, +	GL_TEXTURE_2D, // TYPE_UVEC4, +	GL_TEXTURE_2D, // TYPE_FLOAT, +	GL_TEXTURE_2D, // TYPE_VEC2, +	GL_TEXTURE_2D, // TYPE_VEC3, +	GL_TEXTURE_2D, // TYPE_VEC4, +	GL_TEXTURE_2D, // TYPE_MAT2, +	GL_TEXTURE_2D, // TYPE_MAT3, +	GL_TEXTURE_2D, // TYPE_MAT4, +	GL_TEXTURE_2D, // TYPE_SAMPLER2D, +	GL_TEXTURE_2D, // TYPE_ISAMPLER2D, +	GL_TEXTURE_2D, // TYPE_USAMPLER2D, +	GL_TEXTURE_2D_ARRAY, // TYPE_SAMPLER2DARRAY, +	GL_TEXTURE_2D_ARRAY, // TYPE_ISAMPLER2DARRAY, +	GL_TEXTURE_2D_ARRAY, // TYPE_USAMPLER2DARRAY, +	GL_TEXTURE_3D, // TYPE_SAMPLER3D, +	GL_TEXTURE_3D, // TYPE_ISAMPLER3D, +	GL_TEXTURE_3D, // TYPE_USAMPLER3D, +	GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBE, +	GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBEARRAY, +	GL_TEXTURE_2D, // TYPE_STRUCT +}; +  void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {  	MaterialStorage *material_storage = MaterialStorage::get_singleton();  	bool uses_global_buffer = false; @@ -1275,13 +1311,13 @@ MaterialStorage *MaterialStorage::get_singleton() {  MaterialStorage::MaterialStorage() {  	singleton = this; -	shader_data_request_func[RS::SHADER_SPATIAL] = nullptr; +	shader_data_request_func[RS::SHADER_SPATIAL] = _create_scene_shader_func;  	shader_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_shader_func;  	shader_data_request_func[RS::SHADER_PARTICLES] = nullptr;  	shader_data_request_func[RS::SHADER_SKY] = _create_sky_shader_func;  	shader_data_request_func[RS::SHADER_FOG] = nullptr; -	material_data_request_func[RS::SHADER_SPATIAL] = nullptr; +	material_data_request_func[RS::SHADER_SPATIAL] = _create_scene_material_func;  	material_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_material_func;  	material_data_request_func[RS::SHADER_PARTICLES] = nullptr;  	material_data_request_func[RS::SHADER_SKY] = _create_sky_material_func; @@ -1365,16 +1401,12 @@ MaterialStorage::MaterialStorage() {  		actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";  		actions.render_mode_defines["light_only"] = "#define MODE_LIGHT_ONLY\n"; -		actions.base_texture_binding_index = 0; -		actions.base_uniform_string = ""; -		actions.global_buffer_array_variable = ""; -  		shaders.compiler_canvas.initialize(actions);  	}  	{  		// Setup Scene compiler -		/* +  		//shader compiler  		ShaderCompiler::DefaultIdentifierActions actions; @@ -1529,11 +1561,6 @@ MaterialStorage::MaterialStorage() {  		actions.render_mode_defines["sss_mode_skin"] = "#define SSS_MODE_SKIN\n";  		actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - -		actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; // linear filter with mipmaps -		actions.custom_samplers["DEPTH_TEXTURE"] = "material_samplers[3]"; -		actions.custom_samplers["NORMAL_ROUGHNESS_TEXTURE"] = "material_samplers[1]"; // linear filter -  		actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";  		actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n";  		actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; @@ -1541,19 +1568,10 @@ MaterialStorage::MaterialStorage() {  		actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n";  		actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; -		actions.sampler_array_name = "material_samplers"; -		actions.base_texture_binding_index = 1; -		actions.texture_layout_set = RenderForwardClustered::MATERIAL_UNIFORM_SET; -		actions.base_uniform_string = "material."; -		actions.base_varying_index = 10; -  		actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;  		actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; -		actions.global_buffer_array_variable = "global_variables.data"; -		actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs"; -		compiler.initialize(actions); -		*/ +		shaders.compiler_scene.initialize(actions);  	}  	{ @@ -1664,13 +1682,8 @@ ShaderCompiler::DefaultIdentifierActions actions;  		actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n";  		actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n"; -		actions.base_texture_binding_index = 1; -		actions.texture_layout_set = 1; -		actions.base_varying_index = 10; -  		actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;  		actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; -		actions.global_buffer_array_variable = "global_variables";  		shaders.compiler_sky.initialize(actions);  	} @@ -2914,42 +2927,6 @@ void CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_par  	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);  } -// Look up table to translate ShaderLanguage::DataType to GL_TEXTURE_* -static const GLenum target_from_type[ShaderLanguage::TYPE_MAX] = { -	GL_TEXTURE_2D, // TYPE_VOID, -	GL_TEXTURE_2D, // TYPE_BOOL, -	GL_TEXTURE_2D, // TYPE_BVEC2, -	GL_TEXTURE_2D, // TYPE_BVEC3, -	GL_TEXTURE_2D, // TYPE_BVEC4, -	GL_TEXTURE_2D, // TYPE_INT, -	GL_TEXTURE_2D, // TYPE_IVEC2, -	GL_TEXTURE_2D, // TYPE_IVEC3, -	GL_TEXTURE_2D, // TYPE_IVEC4, -	GL_TEXTURE_2D, // TYPE_UINT, -	GL_TEXTURE_2D, // TYPE_UVEC2, -	GL_TEXTURE_2D, // TYPE_UVEC3, -	GL_TEXTURE_2D, // TYPE_UVEC4, -	GL_TEXTURE_2D, // TYPE_FLOAT, -	GL_TEXTURE_2D, // TYPE_VEC2, -	GL_TEXTURE_2D, // TYPE_VEC3, -	GL_TEXTURE_2D, // TYPE_VEC4, -	GL_TEXTURE_2D, // TYPE_MAT2, -	GL_TEXTURE_2D, // TYPE_MAT3, -	GL_TEXTURE_2D, // TYPE_MAT4, -	GL_TEXTURE_2D, // TYPE_SAMPLER2D, -	GL_TEXTURE_2D, // TYPE_ISAMPLER2D, -	GL_TEXTURE_2D, // TYPE_USAMPLER2D, -	GL_TEXTURE_2D_ARRAY, // TYPE_SAMPLER2DARRAY, -	GL_TEXTURE_2D_ARRAY, // TYPE_ISAMPLER2DARRAY, -	GL_TEXTURE_2D_ARRAY, // TYPE_USAMPLER2DARRAY, -	GL_TEXTURE_3D, // TYPE_SAMPLER3D, -	GL_TEXTURE_3D, // TYPE_ISAMPLER3D, -	GL_TEXTURE_3D, // TYPE_USAMPLER3D, -	GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBE, -	GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBEARRAY, -	GL_TEXTURE_2D, // TYPE_STRUCT -}; -  void CanvasMaterialData::bind_uniforms() {  	// Bind Material Uniforms  	glBindBufferBase(GL_UNIFORM_BUFFER, RasterizerCanvasGLES3::MATERIAL_UNIFORM_BUFFER_OBJECT, uniform_buffer); @@ -2958,7 +2935,7 @@ void CanvasMaterialData::bind_uniforms() {  	ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();  	for (int ti = 0; ti < texture_cache.size(); ti++) {  		Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]); -		glActiveTexture(GL_TEXTURE1 + ti); +		glActiveTexture(GL_TEXTURE1 + ti); // Start at GL_TEXTURE1 because texture slot 0 is used by the base texture  		glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);  		// Set sampler state here as the same texture can be used in multiple places with different flags @@ -3203,4 +3180,297 @@ void SkyMaterialData::bind_uniforms() {  	}  } +//////////////////////////////////////////////////////////////////////////////// +// Scene SHADER + +void SceneShaderData::set_code(const String &p_code) { +	//compile + +	code = p_code; +	valid = false; +	ubo_size = 0; +	uniforms.clear(); +	uses_screen_texture = false; + +	if (code.is_empty()) { +		return; //just invalid, but no error +	} + +	ShaderCompiler::GeneratedCode gen_code; + +	int blend_modei = BLEND_MODE_MIX; +	int depth_testi = DEPTH_TEST_ENABLED; +	int alpha_antialiasing_modei = ALPHA_ANTIALIASING_OFF; +	int cull_modei = CULL_BACK; +	int depth_drawi = DEPTH_DRAW_OPAQUE; + +	uses_point_size = false; +	uses_alpha = false; +	uses_alpha_clip = false; +	uses_blend_alpha = false; +	uses_depth_pre_pass = false; +	uses_discard = false; +	uses_roughness = false; +	uses_normal = false; +	wireframe = false; + +	unshaded = false; +	uses_vertex = false; +	uses_position = false; +	uses_sss = false; +	uses_transmittance = false; +	uses_screen_texture = false; +	uses_depth_texture = false; +	uses_normal_texture = false; +	uses_time = false; +	writes_modelview_or_projection = false; +	uses_world_coordinates = false; +	uses_particle_trails = false; + +	ShaderCompiler::IdentifierActions actions; +	actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX; +	actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT; +	actions.entry_point_stages["light"] = ShaderCompiler::STAGE_FRAGMENT; + +	actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_modei, BLEND_MODE_ADD); +	actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MIX); +	actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_modei, BLEND_MODE_SUB); +	actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MUL); + +	actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE); +	actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE); + +	actions.render_mode_values["depth_draw_never"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_DISABLED); +	actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE); +	actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS); + +	actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED); + +	actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, CULL_DISABLED); +	actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, CULL_FRONT); +	actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, CULL_BACK); + +	actions.render_mode_flags["unshaded"] = &unshaded; +	actions.render_mode_flags["wireframe"] = &wireframe; +	actions.render_mode_flags["particle_trails"] = &uses_particle_trails; + +	actions.usage_flag_pointers["ALPHA"] = &uses_alpha; +	actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip; +	actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; + +	actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; +	actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance; + +	actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; +	actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture; +	actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture; +	actions.usage_flag_pointers["DISCARD"] = &uses_discard; +	actions.usage_flag_pointers["TIME"] = &uses_time; +	actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness; +	actions.usage_flag_pointers["NORMAL"] = &uses_normal; +	actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal; + +	actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size; +	actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size; + +	actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection; +	actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection; +	actions.write_flag_pointers["VERTEX"] = &uses_vertex; +	actions.write_flag_pointers["POSITION"] = &uses_position; + +	actions.uniforms = &uniforms; + +	Error err = MaterialStorage::get_singleton()->shaders.compiler_scene.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code); +	ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); + +	if (version.is_null()) { +		version = MaterialStorage::get_singleton()->shaders.scene_shader.version_create(); +	} + +	depth_draw = DepthDraw(depth_drawi); +	depth_test = DepthTest(depth_testi); +	cull_mode = Cull(cull_modei); +	blend_mode = BlendMode(blend_modei); +	alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei); + +#if 0 +	print_line("**compiling shader:"); +	print_line("**defines:\n"); +	for (int i = 0; i < gen_code.defines.size(); i++) { +		print_line(gen_code.defines[i]); +	} + +	Map<String, String>::Element *el = gen_code.code.front(); +	while (el) { +		print_line("\n**code " + el->key() + ":\n" + el->value()); + +		el = el->next(); +	} + +	print_line("\n**uniforms:\n" + gen_code.uniforms); +	print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]); +	print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]); +#endif + +	Vector<StringName> texture_uniform_names; +	for (int i = 0; i < gen_code.texture_uniforms.size(); i++) { +		texture_uniform_names.push_back(gen_code.texture_uniforms[i].name); +	} + +	MaterialStorage::get_singleton()->shaders.scene_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names); +	ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.scene_shader.version_is_valid(version)); + +	ubo_size = gen_code.uniform_total_size; +	ubo_offsets = gen_code.uniform_offsets; +	texture_uniforms = gen_code.texture_uniforms; + +	// if any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage +	if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) { +		blend_mode = BLEND_MODE_ALPHA_TO_COVERAGE; +	} + +	valid = true; +} + +void SceneShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +	if (!p_texture.is_valid()) { +		if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { +			default_texture_params[p_name].erase(p_index); + +			if (default_texture_params[p_name].is_empty()) { +				default_texture_params.erase(p_name); +			} +		} +	} else { +		if (!default_texture_params.has(p_name)) { +			default_texture_params[p_name] = Map<int, RID>(); +		} +		default_texture_params[p_name][p_index] = p_texture; +	} +} + +void SceneShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +	Map<int, StringName> order; + +	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { +		if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { +			continue; +		} + +		if (E.value.texture_order >= 0) { +			order[E.value.texture_order + 100000] = E.key; +		} else { +			order[E.value.order] = E.key; +		} +	} + +	for (const KeyValue<int, StringName> &E : order) { +		PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); +		pi.name = E.value; +		p_param_list->push_back(pi); +	} +} + +void SceneShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { +	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { +		if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { +			continue; +		} + +		RendererMaterialStorage::InstanceShaderParam p; +		p.info = ShaderLanguage::uniform_to_property_info(E.value); +		p.info.name = E.key; //supply name +		p.index = E.value.instance_index; +		p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); +		p_param_list->push_back(p); +	} +} + +bool SceneShaderData::is_param_texture(const StringName &p_param) const { +	if (!uniforms.has(p_param)) { +		return false; +	} + +	return uniforms[p_param].texture_order >= 0; +} + +bool SceneShaderData::is_animated() const { +	return false; +} + +bool SceneShaderData::casts_shadows() const { +	return false; +} + +Variant SceneShaderData::get_default_parameter(const StringName &p_parameter) const { +	if (uniforms.has(p_parameter)) { +		ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; +		Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; +		return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); +	} +	return Variant(); +} + +RS::ShaderNativeSourceCode SceneShaderData::get_native_source_code() const { +	return MaterialStorage::get_singleton()->shaders.scene_shader.version_get_native_source_code(version); +} + +SceneShaderData::SceneShaderData() { +	valid = false; +	uses_screen_texture = false; +} + +SceneShaderData::~SceneShaderData() { +	if (version.is_valid()) { +		MaterialStorage::get_singleton()->shaders.scene_shader.version_free(version); +	} +} + +GLES3::ShaderData *GLES3::_create_scene_shader_func() { +	SceneShaderData *shader_data = memnew(SceneShaderData); +	return shader_data; +} + +void SceneMaterialData::set_render_priority(int p_priority) { +	priority = p_priority - RS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits +} + +void SceneMaterialData::set_next_pass(RID p_pass) { +	next_pass = p_pass; +} + +void SceneMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +	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); +} + +SceneMaterialData::~SceneMaterialData() { +} + +GLES3::MaterialData *GLES3::_create_scene_material_func(ShaderData *p_shader) { +	SceneMaterialData *material_data = memnew(SceneMaterialData); +	material_data->shader_data = static_cast<SceneShaderData *>(p_shader); +	//update will happen later anyway so do nothing. +	return material_data; +} + +void SceneMaterialData::bind_uniforms() { +	// Bind Material Uniforms +	glBindBufferBase(GL_UNIFORM_BUFFER, 3, uniform_buffer); + +	RID *textures = texture_cache.ptrw(); +	ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw(); +	for (int ti = 0; ti < texture_cache.size(); ti++) { +		Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]); +		glActiveTexture(GL_TEXTURE0 + ti); +		glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id); + +		// Set sampler state here as the same texture can be used in multiple places with different flags +		// Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture* +		RS::CanvasItemTextureFilter filter = RS::CanvasItemTextureFilter((int(texture_uniforms[ti].filter) + 1) % RS::CANVAS_ITEM_TEXTURE_FILTER_MAX); +		RS::CanvasItemTextureRepeat repeat = RS::CanvasItemTextureRepeat((int(texture_uniforms[ti].repeat) + 1) % RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR); +		texture->gl_set_filter(filter); +		texture->gl_set_repeat(repeat); +	} +} +  #endif // !GLES3_ENABLED diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h index 1a7452f66a..f9901f0085 100644 --- a/drivers/gles3/storage/material_storage.h +++ b/drivers/gles3/storage/material_storage.h @@ -45,15 +45,17 @@  #include "drivers/gles3/shaders/copy.glsl.gen.h"  #include "../shaders/canvas.glsl.gen.h" +#include "../shaders/scene.glsl.gen.h"  #include "../shaders/sky.glsl.gen.h"  namespace GLES3 { -/* SHADER Structs */ +/* Shader Structs */  struct Shaders {  	CanvasShaderGLES3 canvas_shader;  	SkyShaderGLES3 sky_shader; +	SceneShaderGLES3 scene_shader;  	ShaderCompiler compiler_canvas;  	ShaderCompiler compiler_scene; @@ -141,7 +143,7 @@ struct Material {  			update_element(this) {}  }; -// CanvasItem Materials +/* CanvasItem Materials */  struct CanvasShaderData : public ShaderData {  	enum BlendMode { //used internally @@ -249,6 +251,126 @@ struct SkyMaterialData : public MaterialData {  MaterialData *_create_sky_material_func(ShaderData *p_shader); +/* Scene Materials */ + +struct SceneShaderData : public ShaderData { +	enum BlendMode { //used internally +		BLEND_MODE_MIX, +		BLEND_MODE_ADD, +		BLEND_MODE_SUB, +		BLEND_MODE_MUL, +		BLEND_MODE_ALPHA_TO_COVERAGE +	}; + +	enum DepthDraw { +		DEPTH_DRAW_DISABLED, +		DEPTH_DRAW_OPAQUE, +		DEPTH_DRAW_ALWAYS +	}; + +	enum DepthTest { +		DEPTH_TEST_DISABLED, +		DEPTH_TEST_ENABLED +	}; + +	enum Cull { +		CULL_DISABLED, +		CULL_FRONT, +		CULL_BACK +	}; + +	enum CullVariant { +		CULL_VARIANT_NORMAL, +		CULL_VARIANT_REVERSED, +		CULL_VARIANT_DOUBLE_SIDED, +		CULL_VARIANT_MAX + +	}; + +	enum AlphaAntiAliasing { +		ALPHA_ANTIALIASING_OFF, +		ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE, +		ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE +	}; + +	bool valid; +	RID version; + +	String path; + +	Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; +	Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; + +	Vector<uint32_t> ubo_offsets; +	uint32_t ubo_size; + +	String code; +	Map<StringName, Map<int, RID>> default_texture_params; + +	BlendMode blend_mode; +	AlphaAntiAliasing alpha_antialiasing_mode; +	DepthDraw depth_draw; +	DepthTest depth_test; +	Cull cull_mode; + +	bool uses_point_size; +	bool uses_alpha; +	bool uses_blend_alpha; +	bool uses_alpha_clip; +	bool uses_depth_pre_pass; +	bool uses_discard; +	bool uses_roughness; +	bool uses_normal; +	bool uses_particle_trails; +	bool wireframe; + +	bool unshaded; +	bool uses_vertex; +	bool uses_position; +	bool uses_sss; +	bool uses_transmittance; +	bool uses_screen_texture; +	bool uses_depth_texture; +	bool uses_normal_texture; +	bool uses_time; +	bool writes_modelview_or_projection; +	bool uses_world_coordinates; + +	uint64_t last_pass = 0; +	uint32_t index = 0; + +	virtual void set_code(const String &p_Code); +	virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); +	virtual void get_param_list(List<PropertyInfo> *p_param_list) const; +	virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; + +	virtual bool is_param_texture(const StringName &p_param) const; +	virtual bool is_animated() const; +	virtual bool casts_shadows() const; +	virtual Variant get_default_parameter(const StringName &p_parameter) const; +	virtual RS::ShaderNativeSourceCode get_native_source_code() const; + +	SceneShaderData(); +	virtual ~SceneShaderData(); +}; + +ShaderData *_create_scene_shader_func(); + +struct SceneMaterialData : public MaterialData { +	SceneShaderData *shader_data = nullptr; +	uint64_t last_pass = 0; +	uint32_t index = 0; +	RID next_pass; +	uint8_t priority = 0; +	virtual void set_render_priority(int p_priority); +	virtual void set_next_pass(RID p_pass); +	virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); +	virtual void bind_uniforms(); +	virtual ~SceneMaterialData(); +}; + +MaterialData *_create_scene_material_func(ShaderData *p_shader); +  /* Global variable structs */  struct GlobalVariables {  	enum { diff --git a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl index 61c8488a05..a3bfb59f92 100644 --- a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl @@ -50,34 +50,4 @@ struct ReflectionData {  	// notes: for ambientblend, use distance to edge to blend between already existing global environment  }; -struct DirectionalLightData { -	mediump vec3 direction; -	mediump float energy; -	mediump vec3 color; -	mediump float size; -	mediump float specular; -	uint mask; -	highp float softshadow_angle; -	highp float soft_shadow_scale; -	bool blend_splits; -	bool shadow_enabled; -	highp float fade_from; -	highp float fade_to; -	uvec2 pad; -	uint bake_mode; -	mediump float shadow_volumetric_fog_fade; -	highp vec4 shadow_bias; -	highp vec4 shadow_normal_bias; -	highp vec4 shadow_transmittance_bias; -	highp vec4 shadow_z_range; -	highp vec4 shadow_range_begin; -	highp vec4 shadow_split_offsets; -	highp mat4 shadow_matrix1; -	highp mat4 shadow_matrix2; -	highp mat4 shadow_matrix3; -	highp mat4 shadow_matrix4; -	highp vec2 uv_scale1; -	highp vec2 uv_scale2; -	highp vec2 uv_scale3; -	highp vec2 uv_scale4; -}; +uv_scale1 diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 3d3226e75b..5669cb2054 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -685,9 +685,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene  				}  				vcode += ";\n"; - -				r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode; -				r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") " + interp_mode + "in " + vcode; +				// GLSL ES 3.0 does not allow layout qualifiers for varyings +				if (!RS::get_singleton()->is_low_end()) { +					r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") "; +					r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") "; +				} +				r_gen_code.stage_globals[STAGE_VERTEX] += interp_mode + "out " + vcode; +				r_gen_code.stage_globals[STAGE_FRAGMENT] += interp_mode + "in " + vcode;  				index += inc;  			}  |