mirror of
https://github.com/godotengine/godot.git
synced 2025-11-01 06:01:14 +00:00
Optimize Mobile renderer by using FP16 explicitly.
This commit is contained in:
parent
8f87e60307
commit
46277836a6
23 changed files with 938 additions and 786 deletions
|
|
@ -5580,7 +5580,7 @@ uint64_t RenderingDeviceDriverD3D12::api_trait_get(ApiTrait p_trait) {
|
|||
|
||||
bool RenderingDeviceDriverD3D12::has_feature(Features p_feature) {
|
||||
switch (p_feature) {
|
||||
case SUPPORTS_FSR_HALF_FLOAT:
|
||||
case SUPPORTS_HALF_FLOAT:
|
||||
return shader_capabilities.native_16bit_ops && storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;
|
||||
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -2725,7 +2725,7 @@ uint64_t RenderingDeviceDriverMetal::api_trait_get(ApiTrait p_trait) {
|
|||
|
||||
bool RenderingDeviceDriverMetal::has_feature(Features p_feature) {
|
||||
switch (p_feature) {
|
||||
case SUPPORTS_FSR_HALF_FLOAT:
|
||||
case SUPPORTS_HALF_FLOAT:
|
||||
return true;
|
||||
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -5888,7 +5888,7 @@ uint64_t RenderingDeviceDriverVulkan::api_trait_get(ApiTrait p_trait) {
|
|||
|
||||
bool RenderingDeviceDriverVulkan::has_feature(Features p_feature) {
|
||||
switch (p_feature) {
|
||||
case SUPPORTS_FSR_HALF_FLOAT:
|
||||
case SUPPORTS_HALF_FLOAT:
|
||||
return shader_capabilities.shader_float16_is_supported && physical_device_features.shaderInt16 && storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;
|
||||
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -130,6 +130,10 @@ bool ShaderBakerExportPlugin::_begin_customize_resources(const Ref<EditorExportP
|
|||
renderer_features.set_flag(RenderingShaderLibrary::FEATURE_VRS_BIT);
|
||||
}
|
||||
|
||||
// Both FP16 and FP32 variants should be included.
|
||||
renderer_features.set_flag(RenderingShaderLibrary::FEATURE_FP16_BIT);
|
||||
renderer_features.set_flag(RenderingShaderLibrary::FEATURE_FP32_BIT);
|
||||
|
||||
RendererSceneRenderRD::get_singleton()->enable_features(renderer_features);
|
||||
|
||||
// Included all shaders created by renderers and effects.
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ FSR::FSR() {
|
|||
fsr_shader.initialize(fsr_upscale_modes);
|
||||
|
||||
FSRShaderVariant variant;
|
||||
if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) {
|
||||
if (RD::get_singleton()->has_feature(RD::SUPPORTS_HALF_FLOAT)) {
|
||||
variant = FSR_SHADER_VARIANT_NORMAL;
|
||||
} else {
|
||||
variant = FSR_SHADER_VARIANT_FALLBACK;
|
||||
|
|
|
|||
|
|
@ -518,7 +518,7 @@ FSR2Effect::FSR2Effect() {
|
|||
capabilities.minimumSupportedShaderModel = FFX_SHADER_MODEL_5_1;
|
||||
capabilities.waveLaneCountMin = 32;
|
||||
capabilities.waveLaneCountMax = 32;
|
||||
capabilities.fp16Supported = RD::get_singleton()->has_feature(RD::Features::SUPPORTS_FSR_HALF_FLOAT);
|
||||
capabilities.fp16Supported = RD::get_singleton()->has_feature(RD::Features::SUPPORTS_HALF_FLOAT);
|
||||
capabilities.raytracingSupported = false;
|
||||
|
||||
String general_defines =
|
||||
|
|
|
|||
|
|
@ -694,14 +694,14 @@ void SceneShaderForwardClustered::init(const String p_defines) {
|
|||
actions.renames["EYE_OFFSET"] = "eye_offset";
|
||||
|
||||
//for light
|
||||
actions.renames["VIEW"] = "view";
|
||||
actions.renames["SPECULAR_AMOUNT"] = "specular_amount";
|
||||
actions.renames["LIGHT_COLOR"] = "light_color";
|
||||
actions.renames["VIEW"] = "view_highp";
|
||||
actions.renames["SPECULAR_AMOUNT"] = "specular_amount_highp";
|
||||
actions.renames["LIGHT_COLOR"] = "light_color_highp";
|
||||
actions.renames["LIGHT_IS_DIRECTIONAL"] = "is_directional";
|
||||
actions.renames["LIGHT"] = "light";
|
||||
actions.renames["ATTENUATION"] = "attenuation";
|
||||
actions.renames["DIFFUSE_LIGHT"] = "diffuse_light";
|
||||
actions.renames["SPECULAR_LIGHT"] = "specular_light";
|
||||
actions.renames["LIGHT"] = "light_highp";
|
||||
actions.renames["ATTENUATION"] = "attenuation_highp";
|
||||
actions.renames["DIFFUSE_LIGHT"] = "diffuse_light_highp";
|
||||
actions.renames["SPECULAR_LIGHT"] = "specular_light_highp";
|
||||
|
||||
actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n";
|
||||
actions.usage_defines["TANGENT"] = "#define TANGENT_USED\n";
|
||||
|
|
|
|||
|
|
@ -380,6 +380,14 @@ uint32_t RenderForwardMobile::get_pipeline_compilations(RS::PipelineSource p_sou
|
|||
}
|
||||
|
||||
void RenderForwardMobile::enable_features(BitField<FeatureBits> p_feature_bits) {
|
||||
if (p_feature_bits.has_flag(FEATURE_FP32_BIT)) {
|
||||
scene_shader.enable_fp32_shader_group();
|
||||
}
|
||||
|
||||
if (p_feature_bits.has_flag(FEATURE_FP16_BIT)) {
|
||||
scene_shader.enable_fp16_shader_group();
|
||||
}
|
||||
|
||||
if (p_feature_bits.has_flag(FEATURE_MULTIVIEW_BIT)) {
|
||||
scene_shader.enable_multiview_shader_group();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -381,7 +381,7 @@ RID SceneShaderForwardMobile::ShaderData::get_shader_variant(ShaderVersion p_sha
|
|||
if (version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
ERR_FAIL_NULL_V(SceneShaderForwardMobile::singleton, RID());
|
||||
return SceneShaderForwardMobile::singleton->shader.version_get_shader(version, p_shader_version + (p_ubershader ? SHADER_VERSION_MAX : 0));
|
||||
return SceneShaderForwardMobile::singleton->shader.version_get_shader(version, p_shader_version + (SceneShaderForwardMobile::singleton->use_fp16 ? SHADER_VERSION_MAX * 2 : 0) + (p_ubershader ? SHADER_VERSION_MAX : 0));
|
||||
} else {
|
||||
return RID();
|
||||
}
|
||||
|
|
@ -389,6 +389,7 @@ RID SceneShaderForwardMobile::ShaderData::get_shader_variant(ShaderVersion p_sha
|
|||
|
||||
uint64_t SceneShaderForwardMobile::ShaderData::get_vertex_input_mask(ShaderVersion p_shader_version, bool p_ubershader) {
|
||||
// Vertex input masks require knowledge of the shader. Since querying the shader can be expensive due to high contention and the necessary mutex, we cache the result instead.
|
||||
// It is intentional for the range of the input masks to be different than the versions available in the shaders as it'll only ever use the regular variants or the FP16 ones.
|
||||
uint32_t input_mask_index = p_shader_version + (p_ubershader ? SHADER_VERSION_MAX : 0);
|
||||
uint64_t input_mask = vertex_input_masks[input_mask_index].load(std::memory_order_relaxed);
|
||||
if (input_mask == 0) {
|
||||
|
|
@ -446,7 +447,8 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) {
|
|||
bool SceneShaderForwardMobile::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
if (shader_data->version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
return update_parameters_uniform_set(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, uniform_set, SceneShaderForwardMobile::singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, true);
|
||||
RID base_shader = SceneShaderForwardMobile::singleton->shader.version_get_shader(shader_data->version, (SceneShaderForwardMobile::singleton->use_fp16 ? SHADER_VERSION_MAX * 2 : 0));
|
||||
return update_parameters_uniform_set(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, uniform_set, base_shader, RenderForwardMobile::MATERIAL_UNIFORM_SET, true, true);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -476,6 +478,9 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() {
|
|||
void SceneShaderForwardMobile::init(const String p_defines) {
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
|
||||
// Store whether the shader will prefer using the FP16 variant.
|
||||
use_fp16 = RD::get_singleton()->has_feature(RD::SUPPORTS_HALF_FLOAT);
|
||||
|
||||
// Immutable samplers : create the shadow sampler to be passed when creating the pipeline.
|
||||
{
|
||||
RD::SamplerState sampler;
|
||||
|
|
@ -490,19 +495,26 @@ void SceneShaderForwardMobile::init(const String p_defines) {
|
|||
|
||||
{
|
||||
Vector<ShaderRD::VariantDefine> shader_versions;
|
||||
for (uint32_t fp16 = 0; fp16 < 2; fp16++) {
|
||||
for (uint32_t ubershader = 0; ubershader < 2; ubershader++) {
|
||||
const String base_define = ubershader ? "\n#define UBERSHADER\n" : "";
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "", true)); // SHADER_VERSION_COLOR_PASS
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "\n#define USE_LIGHTMAP\n", true)); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "\n#define MODE_RENDER_DEPTH\n#define SHADOW_PASS\n", true)); // SHADER_VERSION_SHADOW_PASS, should probably change this to MODE_RENDER_SHADOW because we don't have a depth pass here...
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n#define SHADOW_PASS\n", true)); // SHADER_VERSION_SHADOW_PASS_DP
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n", true)); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
|
||||
String base_define = fp16 ? "\n#define EXPLICIT_FP16\n" : "";
|
||||
int shader_group = fp16 ? SHADER_GROUP_FP16 : SHADER_GROUP_FP32;
|
||||
int shader_group_multiview = fp16 ? SHADER_GROUP_FP16_MULTIVIEW : SHADER_GROUP_FP32_MULTIVIEW;
|
||||
base_define += ubershader ? "\n#define UBERSHADER\n" : "";
|
||||
|
||||
bool default_enabled = (uint32_t(use_fp16) == fp16);
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "", default_enabled)); // SHADER_VERSION_COLOR_PASS
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define USE_LIGHTMAP\n", default_enabled)); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_RENDER_DEPTH\n#define SHADOW_PASS\n", default_enabled)); // SHADER_VERSION_SHADOW_PASS, should probably change this to MODE_RENDER_SHADOW because we don't have a depth pass here...
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n#define SHADOW_PASS\n", default_enabled)); // SHADER_VERSION_SHADOW_PASS_DP
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n", default_enabled)); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
|
||||
|
||||
// Multiview versions of our shaders.
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n", false)); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n", false)); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define SHADOW_PASS\n", false)); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_MOTION_VECTORS\n", false)); // SHADER_VERSION_MOTION_VECTORS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group_multiview, base_define + "\n#define USE_MULTIVIEW\n", false)); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group_multiview, base_define + "\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n", false)); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group_multiview, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define SHADOW_PASS\n", false)); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group_multiview, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_MOTION_VECTORS\n", false)); // SHADER_VERSION_MOTION_VECTORS_MULTIVIEW
|
||||
}
|
||||
}
|
||||
|
||||
Vector<RD::PipelineImmutableSampler> immutable_samplers;
|
||||
|
|
@ -514,7 +526,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
|
|||
shader.initialize(shader_versions, p_defines, immutable_samplers);
|
||||
|
||||
if (RendererCompositorRD::get_singleton()->is_xr_enabled()) {
|
||||
shader.enable_group(SHADER_GROUP_MULTIVIEW);
|
||||
enable_multiview_shader_group();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -536,21 +548,21 @@ void SceneShaderForwardMobile::init(const String p_defines) {
|
|||
actions.renames["MAIN_CAM_INV_VIEW_MATRIX"] = "scene_data.main_cam_inv_view_matrix";
|
||||
|
||||
actions.renames["VERTEX"] = "vertex";
|
||||
actions.renames["NORMAL"] = "normal";
|
||||
actions.renames["TANGENT"] = "tangent";
|
||||
actions.renames["BINORMAL"] = "binormal";
|
||||
actions.renames["NORMAL"] = "normal_highp";
|
||||
actions.renames["TANGENT"] = "tangent_highp";
|
||||
actions.renames["BINORMAL"] = "binormal_highp";
|
||||
actions.renames["POSITION"] = "position";
|
||||
actions.renames["UV"] = "uv_interp";
|
||||
actions.renames["UV2"] = "uv2_interp";
|
||||
actions.renames["COLOR"] = "color_interp";
|
||||
actions.renames["COLOR"] = "color_highp";
|
||||
actions.renames["POINT_SIZE"] = "gl_PointSize";
|
||||
actions.renames["INSTANCE_ID"] = "gl_InstanceIndex";
|
||||
actions.renames["VERTEX_ID"] = "gl_VertexIndex";
|
||||
actions.renames["Z_CLIP_SCALE"] = "z_clip_scale";
|
||||
|
||||
actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold";
|
||||
actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale";
|
||||
actions.renames["ALPHA_ANTIALIASING_EDGE"] = "alpha_antialiasing_edge";
|
||||
actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold_highp";
|
||||
actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale_highp";
|
||||
actions.renames["ALPHA_ANTIALIASING_EDGE"] = "alpha_antialiasing_edge_highp";
|
||||
actions.renames["ALPHA_TEXTURE_COORDINATE"] = "alpha_texture_coordinate";
|
||||
|
||||
//builtins
|
||||
|
|
@ -567,36 +579,36 @@ void SceneShaderForwardMobile::init(const String p_defines) {
|
|||
|
||||
actions.renames["FRAGCOORD"] = "gl_FragCoord";
|
||||
actions.renames["FRONT_FACING"] = "gl_FrontFacing";
|
||||
actions.renames["NORMAL_MAP"] = "normal_map";
|
||||
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
|
||||
actions.renames["BENT_NORMAL_MAP"] = "bent_normal_map";
|
||||
actions.renames["ALBEDO"] = "albedo";
|
||||
actions.renames["ALPHA"] = "alpha";
|
||||
actions.renames["PREMUL_ALPHA_FACTOR"] = "premul_alpha";
|
||||
actions.renames["METALLIC"] = "metallic";
|
||||
actions.renames["SPECULAR"] = "specular";
|
||||
actions.renames["ROUGHNESS"] = "roughness";
|
||||
actions.renames["RIM"] = "rim";
|
||||
actions.renames["RIM_TINT"] = "rim_tint";
|
||||
actions.renames["CLEARCOAT"] = "clearcoat";
|
||||
actions.renames["CLEARCOAT_ROUGHNESS"] = "clearcoat_roughness";
|
||||
actions.renames["ANISOTROPY"] = "anisotropy";
|
||||
actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
|
||||
actions.renames["SSS_STRENGTH"] = "sss_strength";
|
||||
actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color";
|
||||
actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth";
|
||||
actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost";
|
||||
actions.renames["BACKLIGHT"] = "backlight";
|
||||
actions.renames["AO"] = "ao";
|
||||
actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
|
||||
actions.renames["EMISSION"] = "emission";
|
||||
actions.renames["NORMAL_MAP"] = "normal_map_highp";
|
||||
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth_highp";
|
||||
actions.renames["BENT_NORMAL_MAP"] = "bent_normal_map_highp";
|
||||
actions.renames["ALBEDO"] = "albedo_highp";
|
||||
actions.renames["ALPHA"] = "alpha_highp";
|
||||
actions.renames["PREMUL_ALPHA_FACTOR"] = "premul_alpha_highp";
|
||||
actions.renames["METALLIC"] = "metallic_highp";
|
||||
actions.renames["SPECULAR"] = "specular_highp";
|
||||
actions.renames["ROUGHNESS"] = "roughness_highp";
|
||||
actions.renames["RIM"] = "rim_highp";
|
||||
actions.renames["RIM_TINT"] = "rim_tint_highp";
|
||||
actions.renames["CLEARCOAT"] = "clearcoat_highp";
|
||||
actions.renames["CLEARCOAT_ROUGHNESS"] = "clearcoat_roughness_highp";
|
||||
actions.renames["ANISOTROPY"] = "anisotropy_highp";
|
||||
actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow_highp";
|
||||
actions.renames["SSS_STRENGTH"] = "sss_strength_highp";
|
||||
actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color_highp";
|
||||
actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth_highp";
|
||||
actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost_highp";
|
||||
actions.renames["BACKLIGHT"] = "backlight_highp";
|
||||
actions.renames["AO"] = "ao_highp";
|
||||
actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect_highp";
|
||||
actions.renames["EMISSION"] = "emission_highp";
|
||||
actions.renames["POINT_COORD"] = "gl_PointCoord";
|
||||
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
|
||||
actions.renames["SCREEN_UV"] = "screen_uv";
|
||||
actions.renames["DEPTH"] = "gl_FragDepth";
|
||||
actions.renames["FOG"] = "fog";
|
||||
actions.renames["RADIANCE"] = "custom_radiance";
|
||||
actions.renames["IRRADIANCE"] = "custom_irradiance";
|
||||
actions.renames["FOG"] = "fog_highp";
|
||||
actions.renames["RADIANCE"] = "custom_radiance_highp";
|
||||
actions.renames["IRRADIANCE"] = "custom_irradiance_highp";
|
||||
actions.renames["BONE_INDICES"] = "bone_attrib";
|
||||
actions.renames["BONE_WEIGHTS"] = "weight_attrib";
|
||||
actions.renames["CUSTOM0"] = "custom0_attrib";
|
||||
|
|
@ -617,14 +629,14 @@ void SceneShaderForwardMobile::init(const String p_defines) {
|
|||
actions.renames["EYE_OFFSET"] = "eye_offset";
|
||||
|
||||
//for light
|
||||
actions.renames["VIEW"] = "view";
|
||||
actions.renames["SPECULAR_AMOUNT"] = "specular_amount";
|
||||
actions.renames["LIGHT_COLOR"] = "light_color";
|
||||
actions.renames["VIEW"] = "view_highp";
|
||||
actions.renames["SPECULAR_AMOUNT"] = "specular_amount_highp";
|
||||
actions.renames["LIGHT_COLOR"] = "light_color_highp";
|
||||
actions.renames["LIGHT_IS_DIRECTIONAL"] = "is_directional";
|
||||
actions.renames["LIGHT"] = "light";
|
||||
actions.renames["ATTENUATION"] = "attenuation";
|
||||
actions.renames["DIFFUSE_LIGHT"] = "diffuse_light";
|
||||
actions.renames["SPECULAR_LIGHT"] = "specular_light";
|
||||
actions.renames["LIGHT"] = "light_highp";
|
||||
actions.renames["ATTENUATION"] = "attenuation_highp";
|
||||
actions.renames["DIFFUSE_LIGHT"] = "diffuse_light_highp";
|
||||
actions.renames["SPECULAR_LIGHT"] = "specular_light_highp";
|
||||
|
||||
actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n";
|
||||
actions.usage_defines["TANGENT"] = "#define TANGENT_USED\n";
|
||||
|
|
@ -749,7 +761,7 @@ void fragment() {
|
|||
material_storage->material_set_shader(default_material, default_shader);
|
||||
|
||||
MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
|
||||
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
|
||||
default_shader_rd = shader.version_get_shader(md->shader_data->version, (use_fp16 ? SHADER_VERSION_MAX * 2 : 0) + SHADER_VERSION_COLOR_PASS);
|
||||
|
||||
default_material_shader_ptr = md->shader_data;
|
||||
default_material_uniform_set = md->uniform_set;
|
||||
|
|
@ -830,12 +842,34 @@ uint32_t SceneShaderForwardMobile::get_pipeline_compilations(RS::PipelineSource
|
|||
return pipeline_compilations[p_source];
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::enable_fp32_shader_group() {
|
||||
shader.enable_group(SHADER_GROUP_FP32);
|
||||
|
||||
if (is_multiview_shader_group_enabled()) {
|
||||
enable_multiview_shader_group();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::enable_fp16_shader_group() {
|
||||
shader.enable_group(SHADER_GROUP_FP16);
|
||||
|
||||
if (is_multiview_shader_group_enabled()) {
|
||||
enable_multiview_shader_group();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::enable_multiview_shader_group() {
|
||||
shader.enable_group(SHADER_GROUP_MULTIVIEW);
|
||||
if (shader.is_group_enabled(SHADER_GROUP_FP32)) {
|
||||
shader.enable_group(SHADER_GROUP_FP32_MULTIVIEW);
|
||||
}
|
||||
|
||||
if (shader.is_group_enabled(SHADER_GROUP_FP16)) {
|
||||
shader.enable_group(SHADER_GROUP_FP16_MULTIVIEW);
|
||||
}
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::is_multiview_shader_group_enabled() const {
|
||||
return shader.is_group_enabled(SHADER_GROUP_MULTIVIEW);
|
||||
return shader.is_group_enabled(SHADER_GROUP_FP32_MULTIVIEW) || shader.is_group_enabled(SHADER_GROUP_FP16_MULTIVIEW);
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::~SceneShaderForwardMobile() {
|
||||
|
|
|
|||
|
|
@ -74,8 +74,10 @@ public:
|
|||
}
|
||||
|
||||
enum ShaderGroup {
|
||||
SHADER_GROUP_BASE, // Always compiled at the beginning.
|
||||
SHADER_GROUP_MULTIVIEW,
|
||||
SHADER_GROUP_FP32,
|
||||
SHADER_GROUP_FP32_MULTIVIEW,
|
||||
SHADER_GROUP_FP16,
|
||||
SHADER_GROUP_FP16_MULTIVIEW,
|
||||
};
|
||||
|
||||
struct ShaderSpecialization {
|
||||
|
|
@ -311,6 +313,7 @@ public:
|
|||
|
||||
SceneForwardMobileShaderRD shader;
|
||||
ShaderCompiler compiler;
|
||||
bool use_fp16 = false;
|
||||
|
||||
RID default_shader;
|
||||
RID default_material;
|
||||
|
|
@ -344,6 +347,8 @@ public:
|
|||
void init(const String p_defines);
|
||||
void set_default_specialization(const ShaderSpecialization &p_specialization);
|
||||
uint32_t get_pipeline_compilations(RS::PipelineSource p_source);
|
||||
void enable_fp32_shader_group();
|
||||
void enable_fp16_shader_group();
|
||||
void enable_multiview_shader_group();
|
||||
bool is_multiview_shader_group_enabled() const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
struct DecalData {
|
||||
highp mat4 xform; //to decal transform
|
||||
highp vec3 inv_extents;
|
||||
mediump float albedo_mix;
|
||||
highp vec4 albedo_rect;
|
||||
highp vec4 normal_rect;
|
||||
highp vec4 orm_rect;
|
||||
highp vec4 emission_rect;
|
||||
highp vec4 modulate;
|
||||
mediump float emission_energy;
|
||||
mat4 xform; //to decal transform
|
||||
vec3 inv_extents;
|
||||
float albedo_mix;
|
||||
vec4 albedo_rect;
|
||||
vec4 normal_rect;
|
||||
vec4 orm_rect;
|
||||
vec4 emission_rect;
|
||||
vec4 modulate;
|
||||
float emission_energy;
|
||||
uint mask;
|
||||
mediump float upper_fade;
|
||||
mediump float lower_fade;
|
||||
mediump mat3x4 normal_xform;
|
||||
mediump vec3 normal;
|
||||
mediump float normal_fade;
|
||||
float upper_fade;
|
||||
float lower_fade;
|
||||
mat3x4 normal_xform;
|
||||
vec3 normal;
|
||||
float normal_fade;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -541,7 +541,7 @@ void main() {
|
|||
float attenuation = get_omni_attenuation(d, spot_lights.data[light_index].inv_radius, spot_lights.data[light_index].attenuation);
|
||||
|
||||
vec3 spot_dir = spot_lights.data[light_index].direction;
|
||||
highp float cone_angle = spot_lights.data[light_index].cone_angle;
|
||||
float cone_angle = spot_lights.data[light_index].cone_angle;
|
||||
float scos = max(dot(-normalize(light_rel_vec), spot_dir), cone_angle);
|
||||
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cone_angle));
|
||||
attenuation *= 1.0 - pow(spot_rim, spot_lights.data[light_index].cone_attenuation);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
|
||||
#VERSION_DEFINES
|
||||
|
||||
/* Include half precision types. */
|
||||
#include "../half_inc.glsl"
|
||||
|
||||
#include "scene_forward_clustered_inc.glsl"
|
||||
|
||||
#define SHADER_IS_SRGB false
|
||||
|
|
@ -155,8 +158,8 @@ ivec2 multiview_uv(ivec2 uv) {
|
|||
#endif //USE_MULTIVIEW
|
||||
|
||||
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING)
|
||||
layout(location = 12) highp out vec4 diffuse_light_interp;
|
||||
layout(location = 13) highp out vec4 specular_light_interp;
|
||||
layout(location = 12) out vec4 diffuse_light_interp;
|
||||
layout(location = 13) out vec4 specular_light_interp;
|
||||
|
||||
#include "../scene_forward_vertex_lights_inc.glsl"
|
||||
|
||||
|
|
@ -808,6 +811,9 @@ void main() {
|
|||
#define SHADER_IS_SRGB false
|
||||
#define SHADER_SPACE_FAR 0.0
|
||||
|
||||
/* Include half precision types. */
|
||||
#include "../half_inc.glsl"
|
||||
|
||||
#include "scene_forward_clustered_inc.glsl"
|
||||
|
||||
/* Varyings */
|
||||
|
|
@ -929,8 +935,8 @@ ivec2 multiview_uv(ivec2 uv) {
|
|||
}
|
||||
#endif // !USE_MULTIVIEW
|
||||
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING)
|
||||
layout(location = 12) highp in vec4 diffuse_light_interp;
|
||||
layout(location = 13) highp in vec4 specular_light_interp;
|
||||
layout(location = 12) in vec4 diffuse_light_interp;
|
||||
layout(location = 13) in vec4 specular_light_interp;
|
||||
#endif
|
||||
//defines to keep compatibility with vertex
|
||||
|
||||
|
|
@ -1127,14 +1133,14 @@ void fragment_shader(in SceneData scene_data) {
|
|||
vec3 vertex = vertex_interp;
|
||||
#ifdef USE_MULTIVIEW
|
||||
vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz;
|
||||
vec3 view = -normalize(vertex_interp - eye_offset);
|
||||
vec3 view_highp = -normalize(vertex_interp - eye_offset);
|
||||
|
||||
// UV in our combined frustum space is used for certain screen uv processes where it's
|
||||
// overkill to render separate left and right eye views
|
||||
vec2 combined_uv = (combined_projected.xy / combined_projected.w) * 0.5 + 0.5;
|
||||
#else
|
||||
vec3 eye_offset = vec3(0.0, 0.0, 0.0);
|
||||
vec3 view = -normalize(vertex_interp);
|
||||
vec3 view_highp = -normalize(vertex_interp);
|
||||
#endif
|
||||
vec3 albedo = vec3(1.0);
|
||||
vec3 backlight = vec3(0.0);
|
||||
|
|
@ -1260,10 +1266,12 @@ void fragment_shader(in SceneData scene_data) {
|
|||
#ifdef LIGHT_VERTEX_USED
|
||||
vertex = light_vertex;
|
||||
#ifdef USE_MULTIVIEW
|
||||
view = -normalize(vertex - eye_offset);
|
||||
vec3 view = -normalize(vertex - eye_offset);
|
||||
#else
|
||||
view = -normalize(vertex);
|
||||
vec3 view = -normalize(vertex);
|
||||
#endif //USE_MULTIVIEW
|
||||
#else
|
||||
vec3 view = view_highp;
|
||||
#endif //LIGHT_VERTEX_USED
|
||||
|
||||
#ifdef NORMAL_USED
|
||||
|
|
@ -2063,11 +2071,6 @@ void fragment_shader(in SceneData scene_data) {
|
|||
#endif // !AMBIENT_LIGHT_DISABLED
|
||||
#endif //GI !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
|
||||
|
||||
#if !defined(MODE_RENDER_DEPTH)
|
||||
//this saves some VGPRs
|
||||
uint orms = packUnorm4x8(vec4(ao, roughness, metallic, specular));
|
||||
#endif
|
||||
|
||||
// LIGHTING
|
||||
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
|
||||
|
||||
|
|
@ -2455,7 +2458,7 @@ void fragment_shader(in SceneData scene_data) {
|
|||
#else
|
||||
directional_lights.data[i].color * directional_lights.data[i].energy * tint,
|
||||
#endif
|
||||
true, shadow, f0, orms, directional_lights.data[i].specular, albedo, alpha, screen_uv, energy_compensation,
|
||||
true, shadow, f0, roughness, metallic, directional_lights.data[i].specular, albedo, alpha, screen_uv, energy_compensation,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
|
|
@ -2519,7 +2522,7 @@ void fragment_shader(in SceneData scene_data) {
|
|||
continue; // Statically baked light and object uses lightmap, skip
|
||||
}
|
||||
|
||||
light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv, energy_compensation,
|
||||
light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, roughness, metallic, scene_data.taa_frame_count, albedo, alpha, screen_uv, energy_compensation,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
|
|
@ -2536,7 +2539,7 @@ void fragment_shader(in SceneData scene_data) {
|
|||
clearcoat, clearcoat_roughness, geo_normal,
|
||||
#endif // LIGHT_CLEARCOAT_USED
|
||||
#ifdef LIGHT_ANISOTROPY_USED
|
||||
tangent, binormal, anisotropy,
|
||||
binormal, tangent, anisotropy,
|
||||
#endif
|
||||
diffuse_light, direct_specular_light);
|
||||
}
|
||||
|
|
@ -2580,7 +2583,7 @@ void fragment_shader(in SceneData scene_data) {
|
|||
continue; // Statically baked light and object uses lightmap, skip
|
||||
}
|
||||
|
||||
light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, scene_data.taa_frame_count, albedo, alpha, screen_uv, energy_compensation,
|
||||
light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, roughness, metallic, scene_data.taa_frame_count, albedo, alpha, screen_uv, energy_compensation,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
|
|
@ -2597,8 +2600,7 @@ void fragment_shader(in SceneData scene_data) {
|
|||
clearcoat, clearcoat_roughness, geo_normal,
|
||||
#endif // LIGHT_CLEARCOAT_USED
|
||||
#ifdef LIGHT_ANISOTROPY_USED
|
||||
tangent,
|
||||
binormal, anisotropy,
|
||||
binormal, tangent, anisotropy,
|
||||
#endif
|
||||
diffuse_light, direct_specular_light);
|
||||
}
|
||||
|
|
@ -2775,12 +2777,10 @@ void fragment_shader(in SceneData scene_data) {
|
|||
diffuse_light *= albedo; // ambient must be multiplied by albedo at the end
|
||||
|
||||
// apply direct light AO
|
||||
ao = unpackUnorm4x8(orms).x;
|
||||
diffuse_light *= ao;
|
||||
direct_specular_light *= ao;
|
||||
|
||||
// apply metallic
|
||||
metallic = unpackUnorm4x8(orms).z;
|
||||
diffuse_light *= 1.0 - metallic;
|
||||
ambient_light *= 1.0 - metallic;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -207,8 +207,8 @@ bool sc_directional_light_blend_split(uint i) {
|
|||
return ((sc_packed_1() >> (21 + i)) & 1U) != 0;
|
||||
}
|
||||
|
||||
float sc_luminance_multiplier() {
|
||||
return sc_packed_2();
|
||||
half sc_luminance_multiplier() {
|
||||
return half(sc_packed_2());
|
||||
}
|
||||
|
||||
/* Set 0: Base Pass (never changes) */
|
||||
|
|
@ -259,7 +259,7 @@ directional_lights;
|
|||
#define LIGHTMAP_SHADOWMASK_MODE_ONLY 3
|
||||
|
||||
struct Lightmap {
|
||||
mediump mat3 normal_xform;
|
||||
mat3 normal_xform;
|
||||
vec2 light_texture_size;
|
||||
float exposure_normalization;
|
||||
uint flags;
|
||||
|
|
@ -271,7 +271,7 @@ layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
|
|||
lightmaps;
|
||||
|
||||
struct LightmapCapture {
|
||||
mediump vec4 sh[9];
|
||||
vec4 sh[9];
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 8, std140) restrict readonly buffer LightmapCaptures {
|
||||
|
|
@ -279,8 +279,8 @@ layout(set = 0, binding = 8, std140) restrict readonly buffer LightmapCaptures {
|
|||
}
|
||||
lightmap_captures;
|
||||
|
||||
layout(set = 0, binding = 9) uniform mediump texture2D decal_atlas;
|
||||
layout(set = 0, binding = 10) uniform mediump texture2D decal_atlas_srgb;
|
||||
layout(set = 0, binding = 9) uniform texture2D decal_atlas;
|
||||
layout(set = 0, binding = 10) uniform texture2D decal_atlas_srgb;
|
||||
|
||||
layout(set = 0, binding = 11, std430) restrict readonly buffer Decals {
|
||||
DecalData data[];
|
||||
|
|
@ -288,7 +288,7 @@ layout(set = 0, binding = 11, std430) restrict readonly buffer Decals {
|
|||
decals;
|
||||
|
||||
layout(set = 0, binding = 12, std430) restrict readonly buffer GlobalShaderUniformData {
|
||||
highp vec4 data[];
|
||||
vec4 data[];
|
||||
}
|
||||
global_shader_uniforms;
|
||||
|
||||
|
|
@ -309,7 +309,7 @@ struct InstanceData {
|
|||
uint instance_uniforms_ofs; // Base offset in global buffer for instance variables. // 04 - 72
|
||||
uint gi_offset; // GI information when using lightmapping (VCT or lightmap index). // 04 - 76
|
||||
uint layer_mask; // 04 - 80
|
||||
highp vec4 lightmap_uv_scale; // 16 - 96 Doubles as uv_offset when needed.
|
||||
vec4 lightmap_uv_scale; // 16 - 96 Doubles as uv_offset when needed.
|
||||
|
||||
uvec2 reflection_probes; // 08 - 104
|
||||
uvec2 omni_lights; // 08 - 112
|
||||
|
|
@ -328,30 +328,30 @@ instances;
|
|||
|
||||
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
|
||||
|
||||
layout(set = 1, binding = 2) uniform mediump textureCubeArray radiance_cubemap;
|
||||
layout(set = 1, binding = 2) uniform textureCubeArray radiance_cubemap;
|
||||
|
||||
#else
|
||||
|
||||
layout(set = 1, binding = 2) uniform mediump textureCube radiance_cubemap;
|
||||
layout(set = 1, binding = 2) uniform textureCube radiance_cubemap;
|
||||
|
||||
#endif
|
||||
|
||||
layout(set = 1, binding = 3) uniform mediump textureCubeArray reflection_atlas;
|
||||
layout(set = 1, binding = 3) uniform textureCubeArray reflection_atlas;
|
||||
|
||||
layout(set = 1, binding = 4) uniform highp texture2D shadow_atlas;
|
||||
layout(set = 1, binding = 4) uniform texture2D shadow_atlas;
|
||||
|
||||
layout(set = 1, binding = 5) uniform highp texture2D directional_shadow_atlas;
|
||||
layout(set = 1, binding = 5) uniform texture2D directional_shadow_atlas;
|
||||
|
||||
// this needs to change to providing just the lightmap we're using..
|
||||
layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES * 2];
|
||||
|
||||
#ifdef USE_MULTIVIEW
|
||||
layout(set = 1, binding = 9) uniform highp texture2DArray depth_buffer;
|
||||
layout(set = 1, binding = 10) uniform mediump texture2DArray color_buffer;
|
||||
layout(set = 1, binding = 9) uniform texture2DArray depth_buffer;
|
||||
layout(set = 1, binding = 10) uniform texture2DArray color_buffer;
|
||||
#define multiviewSampler sampler2DArray
|
||||
#else
|
||||
layout(set = 1, binding = 9) uniform highp texture2D depth_buffer;
|
||||
layout(set = 1, binding = 10) uniform mediump texture2D color_buffer;
|
||||
layout(set = 1, binding = 9) uniform texture2D depth_buffer;
|
||||
layout(set = 1, binding = 10) uniform texture2D color_buffer;
|
||||
#define multiviewSampler sampler2D
|
||||
#endif // USE_MULTIVIEW
|
||||
|
||||
|
|
@ -375,7 +375,7 @@ layout(set = 1, binding = 13 + 11) uniform sampler SAMPLER_LINEAR_WITH_MIPMAPS_A
|
|||
/* Set 2 Skeleton & Instancing (can change per item) */
|
||||
|
||||
layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms {
|
||||
highp vec4 data[];
|
||||
vec4 data[];
|
||||
}
|
||||
transforms;
|
||||
|
||||
|
|
|
|||
43
servers/rendering/renderer_rd/shaders/half_inc.glsl
Normal file
43
servers/rendering/renderer_rd/shaders/half_inc.glsl
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Use of FP16 in Godot is done explicitly through the types half and hvec.
|
||||
// The extensions must be supported by the system to use this shader.
|
||||
//
|
||||
// If EXPLICIT_FP16 is not defined, all operations will use full precision
|
||||
// floats instead and all casting operations will not be performed.
|
||||
|
||||
#ifndef HALF_INC_H
|
||||
#define HALF_INC_H
|
||||
|
||||
#ifdef EXPLICIT_FP16
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require
|
||||
#extension GL_EXT_shader_16bit_storage : require
|
||||
|
||||
#define HALF_FLT_MIN float16_t(6.10352e-5)
|
||||
#define HALF_FLT_MAX float16_t(65504.0)
|
||||
|
||||
#define half float16_t
|
||||
#define hvec2 f16vec2
|
||||
#define hvec3 f16vec3
|
||||
#define hvec4 f16vec4
|
||||
#define hmat2 f16mat2
|
||||
#define hmat3 f16mat3
|
||||
#define hmat4 f16mat4
|
||||
#define saturateHalf(x) min(float16_t(x), HALF_FLT_MAX)
|
||||
|
||||
#else
|
||||
|
||||
#define HALF_FLT_MIN float(1.175494351e-38F)
|
||||
#define HALF_FLT_MAX float(3.402823466e+38F)
|
||||
|
||||
#define half float
|
||||
#define hvec2 vec2
|
||||
#define hvec3 vec3
|
||||
#define hvec4 vec4
|
||||
#define hmat2 mat2
|
||||
#define hmat3 mat3
|
||||
#define hmat4 mat4
|
||||
#define saturateHalf(x) (x)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // HALF_INC_H
|
||||
|
|
@ -3,31 +3,31 @@
|
|||
#define LIGHT_BAKE_DYNAMIC 2
|
||||
|
||||
struct LightData { //this structure needs to be as packed as possible
|
||||
highp vec3 position;
|
||||
highp float inv_radius;
|
||||
vec3 position;
|
||||
float inv_radius;
|
||||
|
||||
mediump vec3 direction;
|
||||
highp float size;
|
||||
vec3 direction;
|
||||
float size;
|
||||
|
||||
mediump vec3 color;
|
||||
mediump float attenuation;
|
||||
vec3 color;
|
||||
float attenuation;
|
||||
|
||||
mediump float cone_attenuation;
|
||||
mediump float cone_angle;
|
||||
mediump float specular_amount;
|
||||
mediump float shadow_opacity;
|
||||
float cone_attenuation;
|
||||
float cone_angle;
|
||||
float specular_amount;
|
||||
float shadow_opacity;
|
||||
|
||||
highp vec4 atlas_rect; // rect in the shadow atlas
|
||||
highp mat4 shadow_matrix;
|
||||
highp float shadow_bias;
|
||||
highp float shadow_normal_bias;
|
||||
highp float transmittance_bias;
|
||||
highp float soft_shadow_size; // for spot, it's the size in uv coordinates of the light, for omni it's the span angle
|
||||
highp float soft_shadow_scale; // scales the shadow kernel for blurrier shadows
|
||||
vec4 atlas_rect; // rect in the shadow atlas
|
||||
mat4 shadow_matrix;
|
||||
float shadow_bias;
|
||||
float shadow_normal_bias;
|
||||
float transmittance_bias;
|
||||
float soft_shadow_size; // for spot, it's the size in uv coordinates of the light, for omni it's the span angle
|
||||
float soft_shadow_scale; // scales the shadow kernel for blurrier shadows
|
||||
uint mask;
|
||||
mediump float volumetric_fog_energy;
|
||||
float volumetric_fog_energy;
|
||||
uint bake_mode;
|
||||
highp vec4 projector_rect; //projector rect in srgb decal atlas
|
||||
vec4 projector_rect; //projector rect in srgb decal atlas
|
||||
};
|
||||
|
||||
#define REFLECTION_AMBIENT_DISABLED 0
|
||||
|
|
@ -35,13 +35,13 @@ struct LightData { //this structure needs to be as packed as possible
|
|||
#define REFLECTION_AMBIENT_COLOR 2
|
||||
|
||||
struct ReflectionData {
|
||||
highp vec3 box_extents;
|
||||
mediump float index;
|
||||
highp vec3 box_offset;
|
||||
vec3 box_extents;
|
||||
float index;
|
||||
vec3 box_offset;
|
||||
uint mask;
|
||||
mediump vec3 ambient; // ambient color
|
||||
mediump float intensity;
|
||||
mediump float blend_distance;
|
||||
vec3 ambient; // ambient color
|
||||
float intensity;
|
||||
float blend_distance;
|
||||
bool exterior;
|
||||
bool box_project;
|
||||
uint ambient_mode;
|
||||
|
|
@ -50,38 +50,38 @@ struct ReflectionData {
|
|||
float pad1;
|
||||
float pad2;
|
||||
//0-8 is intensity,8-9 is ambient, mode
|
||||
highp mat4 local_matrix; // up to here for spot and omni, rest is for directional
|
||||
mat4 local_matrix; // up to here for spot and omni, rest is for directional
|
||||
// notes: for ambientblend, use distance to edge to blend between already existing global environment
|
||||
};
|
||||
|
||||
struct DirectionalLightData {
|
||||
mediump vec3 direction;
|
||||
highp float energy; // needs to be highp to avoid NaNs being created with high energy values (i.e. when using physical light units and over-exposing the image)
|
||||
mediump vec3 color;
|
||||
mediump float size;
|
||||
mediump float specular;
|
||||
vec3 direction;
|
||||
float energy; // needs to be highp to avoid NaNs being created with high energy values (i.e. when using physical light units and over-exposing the image)
|
||||
vec3 color;
|
||||
float size;
|
||||
float specular;
|
||||
uint mask;
|
||||
highp float softshadow_angle;
|
||||
highp float soft_shadow_scale;
|
||||
float softshadow_angle;
|
||||
float soft_shadow_scale;
|
||||
bool blend_splits;
|
||||
mediump float shadow_opacity;
|
||||
highp float fade_from;
|
||||
highp float fade_to;
|
||||
float shadow_opacity;
|
||||
float fade_from;
|
||||
float fade_to;
|
||||
uvec2 pad;
|
||||
uint bake_mode;
|
||||
mediump float volumetric_fog_energy;
|
||||
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;
|
||||
float volumetric_fog_energy;
|
||||
vec4 shadow_bias;
|
||||
vec4 shadow_normal_bias;
|
||||
vec4 shadow_transmittance_bias;
|
||||
vec4 shadow_z_range;
|
||||
vec4 shadow_range_begin;
|
||||
vec4 shadow_split_offsets;
|
||||
mat4 shadow_matrix1;
|
||||
mat4 shadow_matrix2;
|
||||
mat4 shadow_matrix3;
|
||||
mat4 shadow_matrix4;
|
||||
vec2 uv_scale1;
|
||||
vec2 uv_scale2;
|
||||
vec2 uv_scale3;
|
||||
vec2 uv_scale4;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,60 +13,60 @@
|
|||
#define SCENE_DATA_FLAGS_IN_SHADOW_PASS (1 << 7)
|
||||
|
||||
struct SceneData {
|
||||
highp mat4 projection_matrix;
|
||||
highp mat4 inv_projection_matrix;
|
||||
highp mat4 inv_view_matrix;
|
||||
highp mat4 view_matrix;
|
||||
mat4 projection_matrix;
|
||||
mat4 inv_projection_matrix;
|
||||
mat4 inv_view_matrix;
|
||||
mat4 view_matrix;
|
||||
|
||||
// only used for multiview
|
||||
highp mat4 projection_matrix_view[MAX_VIEWS];
|
||||
highp mat4 inv_projection_matrix_view[MAX_VIEWS];
|
||||
highp vec4 eye_offset[MAX_VIEWS];
|
||||
mat4 projection_matrix_view[MAX_VIEWS];
|
||||
mat4 inv_projection_matrix_view[MAX_VIEWS];
|
||||
vec4 eye_offset[MAX_VIEWS];
|
||||
|
||||
// Used for billboards to cast correct shadows.
|
||||
highp mat4 main_cam_inv_view_matrix;
|
||||
mat4 main_cam_inv_view_matrix;
|
||||
|
||||
highp vec2 viewport_size;
|
||||
highp vec2 screen_pixel_size;
|
||||
vec2 viewport_size;
|
||||
vec2 screen_pixel_size;
|
||||
|
||||
// Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted.
|
||||
highp vec4 directional_penumbra_shadow_kernel[32];
|
||||
highp vec4 directional_soft_shadow_kernel[32];
|
||||
highp vec4 penumbra_shadow_kernel[32];
|
||||
highp vec4 soft_shadow_kernel[32];
|
||||
vec4 directional_penumbra_shadow_kernel[32];
|
||||
vec4 directional_soft_shadow_kernel[32];
|
||||
vec4 penumbra_shadow_kernel[32];
|
||||
vec4 soft_shadow_kernel[32];
|
||||
|
||||
highp vec2 shadow_atlas_pixel_size;
|
||||
highp vec2 directional_shadow_pixel_size;
|
||||
vec2 shadow_atlas_pixel_size;
|
||||
vec2 directional_shadow_pixel_size;
|
||||
|
||||
uint directional_light_count;
|
||||
mediump float dual_paraboloid_side;
|
||||
highp float z_far;
|
||||
highp float z_near;
|
||||
float dual_paraboloid_side;
|
||||
float z_far;
|
||||
float z_near;
|
||||
|
||||
mediump float roughness_limiter_amount;
|
||||
mediump float roughness_limiter_limit;
|
||||
mediump float opaque_prepass_threshold;
|
||||
highp uint flags;
|
||||
float roughness_limiter_amount;
|
||||
float roughness_limiter_limit;
|
||||
float opaque_prepass_threshold;
|
||||
uint flags;
|
||||
|
||||
mediump mat3 radiance_inverse_xform;
|
||||
mat3 radiance_inverse_xform;
|
||||
|
||||
mediump vec4 ambient_light_color_energy;
|
||||
vec4 ambient_light_color_energy;
|
||||
|
||||
mediump float ambient_color_sky_mix;
|
||||
highp float fog_density;
|
||||
highp float fog_height;
|
||||
highp float fog_height_density;
|
||||
float ambient_color_sky_mix;
|
||||
float fog_density;
|
||||
float fog_height;
|
||||
float fog_height_density;
|
||||
|
||||
highp float fog_depth_curve;
|
||||
highp float fog_depth_begin;
|
||||
highp float fog_depth_end;
|
||||
mediump float fog_sun_scatter;
|
||||
float fog_depth_curve;
|
||||
float fog_depth_begin;
|
||||
float fog_depth_end;
|
||||
float fog_sun_scatter;
|
||||
|
||||
mediump vec3 fog_light_color;
|
||||
mediump float fog_aerial_perspective;
|
||||
vec3 fog_light_color;
|
||||
float fog_aerial_perspective;
|
||||
|
||||
highp float time;
|
||||
highp float taa_frame_count;
|
||||
float time;
|
||||
float taa_frame_count;
|
||||
vec2 taa_jitter;
|
||||
|
||||
float emissive_exposure_normalization;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ float hash_3d(vec3 p) {
|
|||
return hash_2d(vec2(hash_2d(p.xy), p.z));
|
||||
}
|
||||
|
||||
float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {
|
||||
half compute_alpha_hash_threshold(vec3 pos, float hash_scale) {
|
||||
vec3 dx = dFdx(pos);
|
||||
vec3 dy = dFdy(pos);
|
||||
|
||||
|
|
@ -35,24 +35,24 @@ float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {
|
|||
float alpha_hash_threshold =
|
||||
(a_interp < (1.0 - min_lerp)) ? ((a_interp < min_lerp) ? cases.x : cases.y) : cases.z;
|
||||
|
||||
return clamp(alpha_hash_threshold, 0.00001, 1.0);
|
||||
return half(clamp(alpha_hash_threshold, 0.00001, 1.0));
|
||||
}
|
||||
|
||||
#endif // ALPHA_HASH_USED
|
||||
|
||||
#ifdef ALPHA_ANTIALIASING_EDGE_USED
|
||||
|
||||
float calc_mip_level(vec2 texture_coord) {
|
||||
half calc_mip_level(vec2 texture_coord) {
|
||||
vec2 dx = dFdx(texture_coord);
|
||||
vec2 dy = dFdy(texture_coord);
|
||||
float delta_max_sqr = max(dot(dx, dx), dot(dy, dy));
|
||||
return max(0.0, 0.5 * log2(delta_max_sqr));
|
||||
return max(half(0.0), half(0.5) * half(log2(delta_max_sqr)));
|
||||
}
|
||||
|
||||
float compute_alpha_antialiasing_edge(float input_alpha, vec2 texture_coord, float alpha_edge) {
|
||||
input_alpha *= 1.0 + max(0, calc_mip_level(texture_coord)) * 0.25; // 0.25 mip scale, magic number
|
||||
input_alpha = (input_alpha - alpha_edge) / max(fwidth(input_alpha), 0.0001) + 0.5;
|
||||
return clamp(input_alpha, 0.0, 1.0);
|
||||
half compute_alpha_antialiasing_edge(half input_alpha, vec2 texture_coord, half alpha_edge) {
|
||||
input_alpha *= half(1.0) + calc_mip_level(texture_coord) * half(0.25);
|
||||
input_alpha = (input_alpha - alpha_edge) / max(fwidth(input_alpha), half(0.0001)) + half(0.5);
|
||||
return clamp(input_alpha, half(0.0), half(1.0));
|
||||
}
|
||||
|
||||
#endif // ALPHA_ANTIALIASING_USED
|
||||
|
|
|
|||
|
|
@ -13,69 +13,72 @@
|
|||
#define SPEC_CONSTANT_LOOP_ANNOTATION
|
||||
#endif
|
||||
|
||||
float D_GGX(float cos_theta_m, float alpha) {
|
||||
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);
|
||||
half D_GGX(half NoH, half roughness, hvec3 n, hvec3 h) {
|
||||
half a = NoH * roughness;
|
||||
#ifdef EXPLICIT_FP16
|
||||
hvec3 NxH = cross(n, h);
|
||||
half k = roughness / (dot(NxH, NxH) + a * a);
|
||||
#else
|
||||
float k = roughness / (1.0 - NoH * NoH + a * a);
|
||||
#endif
|
||||
half d = k * k * half(1.0 / M_PI);
|
||||
return saturateHalf(d);
|
||||
}
|
||||
|
||||
// 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);
|
||||
half V_GGX(half NdotL, half NdotV, half alpha) {
|
||||
half v = half(0.5) / mix(half(2.0) * NdotL * NdotV, NdotL + NdotV, alpha);
|
||||
return saturateHalf(v);
|
||||
}
|
||||
|
||||
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 * cos_theta_m);
|
||||
highp float v2 = dot(v, v);
|
||||
float w2 = alpha2 / v2;
|
||||
float D = alpha2 * w2 * w2 * (1.0 / M_PI);
|
||||
return D;
|
||||
half D_GGX_anisotropic(half cos_theta_m, half alpha_x, half alpha_y, half cos_phi, half sin_phi) {
|
||||
half alpha2 = alpha_x * alpha_y;
|
||||
vec3 v = vec3(alpha_y * cos_phi, alpha_x * sin_phi, alpha2 * cos_theta_m);
|
||||
float v2 = dot(v, v);
|
||||
half w2 = half(float(alpha2) / v2);
|
||||
return alpha2 * w2 * w2 * half(1.0 / M_PI);
|
||||
}
|
||||
|
||||
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);
|
||||
half V_GGX_anisotropic(half alpha_x, half alpha_y, half TdotV, half TdotL, half BdotV, half BdotL, half NdotV, half NdotL) {
|
||||
half Lambda_V = NdotL * length(hvec3(alpha_x * TdotV, alpha_y * BdotV, NdotV));
|
||||
half Lambda_L = NdotV * length(hvec3(alpha_x * TdotL, alpha_y * BdotL, NdotL));
|
||||
half v = half(0.5) / (Lambda_V + Lambda_L);
|
||||
return saturateHalf(v);
|
||||
}
|
||||
|
||||
float SchlickFresnel(float u) {
|
||||
float m = 1.0 - u;
|
||||
float m2 = m * m;
|
||||
half SchlickFresnel(half u) {
|
||||
half m = half(1.0) - u;
|
||||
half m2 = m * m;
|
||||
return m2 * m2 * m; // pow(m,5)
|
||||
}
|
||||
|
||||
vec3 F0(float metallic, float specular, vec3 albedo) {
|
||||
float dielectric = 0.16 * specular * specular;
|
||||
hvec3 F0(half metallic, half specular, hvec3 albedo) {
|
||||
half dielectric = half(0.16) * specular * specular;
|
||||
// use albedo * metallic as colored specular reflectance at 0 angle for metallic materials;
|
||||
// see https://google.github.io/filament/Filament.md.html
|
||||
return mix(vec3(dielectric), albedo, vec3(metallic));
|
||||
return mix(hvec3(dielectric), albedo, hvec3(metallic));
|
||||
}
|
||||
|
||||
void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_directional, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha, vec2 screen_uv, vec3 energy_compensation,
|
||||
void light_compute(hvec3 N, hvec3 L, hvec3 V, half A, hvec3 light_color, bool is_directional, half attenuation, hvec3 f0, half roughness, half metallic, half specular_amount, hvec3 albedo, inout half alpha, vec2 screen_uv, hvec3 energy_compensation,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
vec3 backlight,
|
||||
hvec3 backlight,
|
||||
#endif
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
vec4 transmittance_color,
|
||||
float transmittance_depth,
|
||||
float transmittance_boost,
|
||||
float transmittance_z,
|
||||
hvec4 transmittance_color,
|
||||
half transmittance_depth,
|
||||
half transmittance_boost,
|
||||
half transmittance_z,
|
||||
#endif
|
||||
#ifdef LIGHT_RIM_USED
|
||||
float rim, float rim_tint,
|
||||
half rim, half rim_tint,
|
||||
#endif
|
||||
#ifdef LIGHT_CLEARCOAT_USED
|
||||
float clearcoat, float clearcoat_roughness, vec3 vertex_normal,
|
||||
half clearcoat, half clearcoat_roughness, hvec3 vertex_normal,
|
||||
#endif
|
||||
#ifdef LIGHT_ANISOTROPY_USED
|
||||
vec3 B, vec3 T, float anisotropy,
|
||||
hvec3 B, hvec3 T, half anisotropy,
|
||||
#endif
|
||||
inout vec3 diffuse_light, inout vec3 specular_light) {
|
||||
vec4 orms_unpacked = unpackUnorm4x8(orms);
|
||||
float roughness = orms_unpacked.y;
|
||||
float metallic = orms_unpacked.z;
|
||||
|
||||
inout hvec3 diffuse_light, inout hvec3 specular_light) {
|
||||
#if defined(LIGHT_CODE_USED)
|
||||
// Light is written by the user shader.
|
||||
mat4 inv_view_matrix = scene_data_block.data.inv_view_matrix;
|
||||
|
|
@ -93,66 +96,71 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_di
|
|||
#define inv_projection_matrix scene_data_block.data.inv_projection_matrix
|
||||
|
||||
vec2 read_viewport_size = scene_data_block.data.viewport_size;
|
||||
vec3 normal = N;
|
||||
vec3 light = L;
|
||||
vec3 view = V;
|
||||
vec3 normal_highp = vec3(N);
|
||||
vec3 light_highp = vec3(L);
|
||||
vec3 view_highp = vec3(V);
|
||||
float specular_amount_highp = float(specular_amount);
|
||||
vec3 light_color_highp = vec3(light_color);
|
||||
float attenuation_highp = float(attenuation);
|
||||
vec3 diffuse_light_highp = vec3(diffuse_light);
|
||||
vec3 specular_light_highp = vec3(specular_light);
|
||||
|
||||
#CODE : LIGHT
|
||||
|
||||
diffuse_light = hvec3(diffuse_light_highp);
|
||||
specular_light = hvec3(specular_light_highp);
|
||||
#else // !LIGHT_CODE_USED
|
||||
float NdotL = min(A + dot(N, L), 1.0);
|
||||
float cNdotV = max(dot(N, V), 1e-4);
|
||||
half NdotL = min(A + dot(N, L), half(1.0));
|
||||
half cNdotV = max(dot(N, V), half(1e-4));
|
||||
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
{
|
||||
#ifdef SSS_MODE_SKIN
|
||||
float scale = 8.25 / transmittance_depth;
|
||||
float d = scale * abs(transmittance_z);
|
||||
float dd = -d * d;
|
||||
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
|
||||
half scale = half(8.25) / transmittance_depth;
|
||||
half d = scale * abs(transmittance_z);
|
||||
float dd = float(-d * d);
|
||||
hvec3 profile = hvec3(vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
|
||||
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
|
||||
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
|
||||
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
|
||||
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
|
||||
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
|
||||
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41));
|
||||
|
||||
diffuse_light += profile * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI);
|
||||
diffuse_light += profile * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, half(0.0), half(1.0)) * half(1.0 / M_PI);
|
||||
#else
|
||||
|
||||
float scale = 8.25 / transmittance_depth;
|
||||
float d = scale * abs(transmittance_z);
|
||||
float dd = -d * d;
|
||||
diffuse_light += exp(dd) * transmittance_color.rgb * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI);
|
||||
half scale = half(8.25) / transmittance_depth;
|
||||
half d = scale * abs(transmittance_z);
|
||||
half dd = -d * d;
|
||||
diffuse_light += exp(dd) * transmittance_color.rgb * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, half(0.0), half(1.0)) * half(1.0 / M_PI);
|
||||
#endif
|
||||
}
|
||||
#endif //LIGHT_TRANSMITTANCE_USED
|
||||
|
||||
#if defined(LIGHT_RIM_USED)
|
||||
// Epsilon min to prevent pow(0, 0) singularity which results in undefined behavior.
|
||||
float rim_light = pow(max(1e-4, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
|
||||
diffuse_light += rim_light * rim * mix(vec3(1.0), albedo, rim_tint) * light_color;
|
||||
half rim_light = pow(max(half(1e-4), half(1.0) - cNdotV), max(half(0.0), (half(1.0) - roughness) * half(16.0)));
|
||||
diffuse_light += rim_light * rim * mix(hvec3(1.0), albedo, rim_tint) * light_color;
|
||||
#endif
|
||||
|
||||
// We skip checking on attenuation on directional lights to avoid a branch that is not as beneficial for directional lights as the other ones.
|
||||
const float EPSILON = 1e-6f;
|
||||
if (is_directional || attenuation > EPSILON) {
|
||||
float cNdotL = max(NdotL, 0.0);
|
||||
if (is_directional || attenuation > HALF_FLT_MIN) {
|
||||
half cNdotL = max(NdotL, half(0.0));
|
||||
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
|
||||
vec3 H = normalize(V + L);
|
||||
#endif
|
||||
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
|
||||
float cLdotH = clamp(A + dot(L, H), 0.0, 1.0);
|
||||
hvec3 H = normalize(V + L);
|
||||
half cLdotH = clamp(A + dot(L, H), half(0.0), half(1.0));
|
||||
#endif
|
||||
#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);
|
||||
float cLdotH5 = SchlickFresnel(cLdotH);
|
||||
half ccNdotL = clamp(A + dot(vertex_normal, L), half(0.0), half(1.0));
|
||||
half ccNdotH = clamp(A + dot(vertex_normal, H), half(0.0), half(1.0));
|
||||
half ccNdotV = max(dot(vertex_normal, V), half(1e-4));
|
||||
half cLdotH5 = SchlickFresnel(cLdotH);
|
||||
|
||||
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 clearcoat_specular_brdf_NL = clearcoat * Gr * Fr * Dr * cNdotL;
|
||||
half Dr = D_GGX(ccNdotH, half(mix(half(0.001), half(0.1), clearcoat_roughness)), vertex_normal, H);
|
||||
half Gr = half(0.25) / (cLdotH * cLdotH);
|
||||
half Fr = mix(half(0.04), half(1.0), cLdotH5);
|
||||
half clearcoat_specular_brdf_NL = clearcoat * Gr * Fr * Dr * cNdotL;
|
||||
|
||||
specular_light += clearcoat_specular_brdf_NL * light_color * attenuation * specular_amount;
|
||||
|
||||
|
|
@ -160,48 +168,49 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_di
|
|||
// but to do so we need to rearrange this entire function
|
||||
#endif // LIGHT_CLEARCOAT_USED
|
||||
|
||||
if (metallic < 1.0) {
|
||||
float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
|
||||
if (metallic < half(1.0)) {
|
||||
half diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
|
||||
|
||||
#if defined(DIFFUSE_LAMBERT_WRAP)
|
||||
// Energy conserving lambert wrap shader.
|
||||
// https://web.archive.org/web/20210228210901/http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/
|
||||
diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))) * (1.0 / M_PI);
|
||||
half op_roughness = half(1.0) + roughness;
|
||||
diffuse_brdf_NL = max(half(0.0), (NdotL + roughness) / (op_roughness * op_roughness)) * half(1.0 / M_PI);
|
||||
#elif defined(DIFFUSE_TOON)
|
||||
|
||||
diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL) * (1.0 / M_PI);
|
||||
diffuse_brdf_NL = smoothstep(-roughness, max(roughness, half(0.01)), NdotL) * half(1.0 / M_PI);
|
||||
|
||||
#elif defined(DIFFUSE_BURLEY)
|
||||
{
|
||||
float FD90_minus_1 = 2.0 * cLdotH * cLdotH * roughness - 0.5;
|
||||
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;
|
||||
half FD90_minus_1 = half(2.0) * cLdotH * cLdotH * roughness - half(0.5);
|
||||
half FdV = half(1.0) + FD90_minus_1 * SchlickFresnel(cNdotV);
|
||||
half FdL = half(1.0) + FD90_minus_1 * SchlickFresnel(cNdotL);
|
||||
diffuse_brdf_NL = half(1.0 / M_PI) * FdV * FdL * cNdotL;
|
||||
}
|
||||
#else
|
||||
// lambert
|
||||
diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
|
||||
diffuse_brdf_NL = cNdotL * half(1.0 / M_PI);
|
||||
#endif
|
||||
|
||||
diffuse_light += light_color * diffuse_brdf_NL * attenuation;
|
||||
|
||||
#if defined(LIGHT_BACKLIGHT_USED)
|
||||
diffuse_light += light_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;
|
||||
diffuse_light += light_color * (hvec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (roughness > 0.0) {
|
||||
if (roughness > half(0.0)) {
|
||||
#if defined(SPECULAR_SCHLICK_GGX)
|
||||
float cNdotH = clamp(A + dot(N, H), 0.0, 1.0);
|
||||
half cNdotH = clamp(A + dot(N, H), half(0.0), half(1.0));
|
||||
#endif
|
||||
// Apply specular light.
|
||||
// FIXME: roughness == 0 should not disable specular light entirely
|
||||
#if defined(SPECULAR_TOON)
|
||||
vec3 R = normalize(-reflect(L, N));
|
||||
float RdotV = dot(R, V);
|
||||
float mid = 1.0 - roughness;
|
||||
hvec3 R = normalize(-reflect(L, N));
|
||||
half RdotV = dot(R, V);
|
||||
half mid = half(1.0) - roughness;
|
||||
mid *= mid;
|
||||
float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
|
||||
half intensity = smoothstep(mid - roughness * half(0.5), mid + roughness * half(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)
|
||||
|
|
@ -209,34 +218,34 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_di
|
|||
|
||||
#elif defined(SPECULAR_SCHLICK_GGX)
|
||||
// shlick+ggx as default
|
||||
float alpha_ggx = roughness * roughness;
|
||||
half 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);
|
||||
float G = V_GGX_anisotropic(ax, ay, dot(T, V), dot(T, L), dot(B, V), dot(B, L), cNdotV, cNdotL);
|
||||
half aspect = sqrt(half(1.0) - anisotropy * half(0.9));
|
||||
half ax = alpha_ggx / aspect;
|
||||
half ay = alpha_ggx * aspect;
|
||||
half XdotH = dot(T, H);
|
||||
half YdotH = dot(B, H);
|
||||
half D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH);
|
||||
half G = V_GGX_anisotropic(ax, ay, dot(T, V), dot(T, L), dot(B, V), dot(B, L), cNdotV, cNdotL);
|
||||
#else // LIGHT_ANISOTROPY_USED
|
||||
float D = D_GGX(cNdotH, alpha_ggx);
|
||||
float G = V_GGX(cNdotL, cNdotV, alpha_ggx);
|
||||
half D = D_GGX(cNdotH, alpha_ggx, N, H);
|
||||
half G = V_GGX(cNdotL, cNdotV, alpha_ggx);
|
||||
#endif // LIGHT_ANISOTROPY_USED
|
||||
// F
|
||||
#if !defined(LIGHT_CLEARCOAT_USED)
|
||||
float cLdotH5 = SchlickFresnel(cLdotH);
|
||||
half cLdotH5 = SchlickFresnel(cLdotH);
|
||||
#endif
|
||||
// Calculate Fresnel using specular occlusion term from Filament:
|
||||
// https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion
|
||||
float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), metallic, 1.0);
|
||||
vec3 F = f0 + (f90 - f0) * cLdotH5;
|
||||
vec3 specular_brdf_NL = energy_compensation * (cNdotL * D * F * G);
|
||||
half f90 = clamp(dot(f0, hvec3(50.0 * 0.33)), metallic, half(1.0));
|
||||
hvec3 F = f0 + (f90 - f0) * cLdotH5;
|
||||
hvec3 specular_brdf_NL = energy_compensation * cNdotL * D * F * G;
|
||||
specular_light += specular_brdf_NL * light_color * attenuation * specular_amount;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_SHADOW_TO_OPACITY
|
||||
alpha = min(alpha, clamp(1.0 - attenuation, 0.0, 1.0));
|
||||
alpha = min(alpha, clamp(half(1.0 - attenuation), half(0.0), half(1.0)));
|
||||
#endif
|
||||
}
|
||||
#endif // LIGHT_CODE_USED
|
||||
|
|
@ -251,13 +260,13 @@ float quick_hash(vec2 pos) {
|
|||
return fract(magic.z * fract(dot(pos, magic.xy)));
|
||||
}
|
||||
|
||||
float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord, float taa_frame_count) {
|
||||
half sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord, float taa_frame_count) {
|
||||
vec2 pos = coord.xy;
|
||||
float depth = coord.z;
|
||||
|
||||
//if only one sample is taken, take it from the center
|
||||
if (sc_directional_soft_shadow_samples() == 0) {
|
||||
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
|
||||
return half(textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)));
|
||||
}
|
||||
|
||||
mat2 disk_rotation;
|
||||
|
|
@ -275,16 +284,16 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve
|
|||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data_block.data.directional_soft_shadow_kernel[i].xy), depth, 1.0));
|
||||
}
|
||||
|
||||
return avg * (1.0 / float(sc_directional_soft_shadow_samples()));
|
||||
return half(avg * (1.0 / float(sc_directional_soft_shadow_samples())));
|
||||
}
|
||||
|
||||
float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord, float taa_frame_count) {
|
||||
half sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord, float taa_frame_count) {
|
||||
vec2 pos = coord.xy;
|
||||
float depth = coord.z;
|
||||
|
||||
//if only one sample is taken, take it from the center
|
||||
if (sc_soft_shadow_samples() == 0) {
|
||||
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
|
||||
return half(textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)));
|
||||
}
|
||||
|
||||
mat2 disk_rotation;
|
||||
|
|
@ -302,15 +311,15 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord, fl
|
|||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data_block.data.soft_shadow_kernel[i].xy), depth, 1.0));
|
||||
}
|
||||
|
||||
return avg * (1.0 / float(sc_soft_shadow_samples()));
|
||||
return half(avg * (1.0 / float(sc_soft_shadow_samples())));
|
||||
}
|
||||
|
||||
float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec4 uv_rect, vec2 flip_offset, float depth, float taa_frame_count) {
|
||||
half sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec4 uv_rect, vec2 flip_offset, float depth, float taa_frame_count) {
|
||||
//if only one sample is taken, take it from the center
|
||||
if (sc_soft_shadow_samples() == 0) {
|
||||
vec2 pos = coord * 0.5 + 0.5;
|
||||
pos = uv_rect.xy + pos * uv_rect.zw;
|
||||
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
|
||||
return half(textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)));
|
||||
}
|
||||
|
||||
mat2 disk_rotation;
|
||||
|
|
@ -346,10 +355,10 @@ float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec
|
|||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(sample_coord, depth, 1.0));
|
||||
}
|
||||
|
||||
return avg * (1.0 / float(sc_soft_shadow_samples()));
|
||||
return half(avg * (1.0 / float(sc_soft_shadow_samples())));
|
||||
}
|
||||
|
||||
float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale, float taa_frame_count) {
|
||||
half sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale, float taa_frame_count) {
|
||||
//find blocker
|
||||
float blocker_count = 0.0;
|
||||
float blocker_average = 0.0;
|
||||
|
|
@ -386,62 +395,62 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
|
|||
s += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(suv, pssm_coord.z, 1.0));
|
||||
}
|
||||
|
||||
return s / float(sc_directional_penumbra_shadow_samples());
|
||||
return half(s / float(sc_directional_penumbra_shadow_samples()));
|
||||
|
||||
} else {
|
||||
//no blockers found, so no shadow
|
||||
return 1.0;
|
||||
return half(1.0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SHADOWS_DISABLED
|
||||
|
||||
float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||
half 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);
|
||||
return half(nd * pow(max(distance, 0.0001), -decay));
|
||||
}
|
||||
|
||||
void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float taa_frame_count, vec3 albedo, inout float alpha, vec2 screen_uv, vec3 energy_compensation,
|
||||
void light_process_omni(uint idx, vec3 vertex, hvec3 eye_vec, hvec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, hvec3 f0, half roughness, half metallic, float taa_frame_count, hvec3 albedo, inout half alpha, vec2 screen_uv, hvec3 energy_compensation,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
vec3 backlight,
|
||||
hvec3 backlight,
|
||||
#endif
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
vec4 transmittance_color,
|
||||
float transmittance_depth,
|
||||
float transmittance_boost,
|
||||
hvec4 transmittance_color,
|
||||
half transmittance_depth,
|
||||
half transmittance_boost,
|
||||
#endif
|
||||
#ifdef LIGHT_RIM_USED
|
||||
float rim, float rim_tint,
|
||||
half rim, half rim_tint,
|
||||
#endif
|
||||
#ifdef LIGHT_CLEARCOAT_USED
|
||||
float clearcoat, float clearcoat_roughness, vec3 vertex_normal,
|
||||
half clearcoat, half clearcoat_roughness, hvec3 vertex_normal,
|
||||
#endif
|
||||
#ifdef LIGHT_ANISOTROPY_USED
|
||||
vec3 binormal, vec3 tangent, float anisotropy,
|
||||
hvec3 binormal, hvec3 tangent, half anisotropy,
|
||||
#endif
|
||||
inout vec3 diffuse_light, inout vec3 specular_light) {
|
||||
const float EPSILON = 1e-6f;
|
||||
inout hvec3 diffuse_light, inout hvec3 specular_light) {
|
||||
|
||||
// Omni light attenuation.
|
||||
vec3 light_rel_vec = omni_lights.data[idx].position - vertex;
|
||||
float light_length = length(light_rel_vec);
|
||||
float omni_attenuation = get_omni_attenuation(light_length, omni_lights.data[idx].inv_radius, omni_lights.data[idx].attenuation);
|
||||
half omni_attenuation = get_omni_attenuation(light_length, omni_lights.data[idx].inv_radius, omni_lights.data[idx].attenuation);
|
||||
|
||||
// Compute size.
|
||||
float size = 0.0;
|
||||
half size = half(0.0);
|
||||
if (sc_use_light_soft_shadows() && omni_lights.data[idx].size > 0.0) {
|
||||
float t = omni_lights.data[idx].size / max(0.001, light_length);
|
||||
size = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
|
||||
half t = half(omni_lights.data[idx].size / max(0.001, light_length));
|
||||
size = half(1.0) / sqrt(half(1.0) + t * t);
|
||||
size = max(half(1.0) - size, half(0.0));
|
||||
}
|
||||
|
||||
float shadow = 1.0;
|
||||
half shadow = half(1.0);
|
||||
#ifndef SHADOWS_DISABLED
|
||||
// Omni light shadow.
|
||||
if (omni_attenuation > EPSILON && omni_lights.data[idx].shadow_opacity > 0.001) {
|
||||
if (omni_attenuation > HALF_FLT_MIN && omni_lights.data[idx].shadow_opacity > 0.001) {
|
||||
// there is a shadowmap
|
||||
vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size;
|
||||
vec4 base_uv_rect = omni_lights.data[idx].atlas_rect;
|
||||
|
|
@ -456,7 +465,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
float shadow_len = length(local_vert); //need to remember shadow len from here
|
||||
vec3 shadow_dir = normalize(local_vert);
|
||||
|
||||
vec3 local_normal = normalize(mat3(omni_lights.data[idx].shadow_matrix) * normal);
|
||||
vec3 local_normal = normalize(mat3(omni_lights.data[idx].shadow_matrix) * vec3(normal));
|
||||
vec3 normal_bias = local_normal * omni_lights.data[idx].shadow_normal_bias * (1.0 - abs(dot(local_normal, shadow_dir)));
|
||||
|
||||
if (sc_use_light_soft_shadows() && omni_lights.data[idx].soft_shadow_size > 0.0) {
|
||||
|
|
@ -520,7 +529,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
|
||||
z_norm += omni_lights.data[idx].inv_radius * omni_lights.data[idx].shadow_bias;
|
||||
|
||||
shadow = 0.0;
|
||||
shadow = half(0.0);
|
||||
|
||||
SPEC_CONSTANT_LOOP_ANNOTATION
|
||||
for (uint i = 0; i < sc_penumbra_shadow_samples(); i++) {
|
||||
|
|
@ -541,15 +550,15 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
|
||||
pos.xy = pos.xy * 0.5 + 0.5;
|
||||
pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
|
||||
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(pos.xy, z_norm, 1.0));
|
||||
shadow += half(textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(pos.xy, z_norm, 1.0)));
|
||||
}
|
||||
|
||||
shadow /= float(sc_penumbra_shadow_samples());
|
||||
shadow = mix(1.0, shadow, omni_lights.data[idx].shadow_opacity);
|
||||
shadow /= half(sc_penumbra_shadow_samples());
|
||||
shadow = mix(half(1.0), shadow, half(omni_lights.data[idx].shadow_opacity));
|
||||
|
||||
} else {
|
||||
//no blockers found, so no shadow
|
||||
shadow = 1.0;
|
||||
shadow = half(1.0);
|
||||
}
|
||||
} else {
|
||||
vec4 uv_rect = base_uv_rect;
|
||||
|
|
@ -565,7 +574,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
float depth = shadow_len - omni_lights.data[idx].shadow_bias;
|
||||
depth *= omni_lights.data[idx].inv_radius;
|
||||
depth = 1.0 - depth;
|
||||
shadow = mix(1.0, sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth, taa_frame_count), omni_lights.data[idx].shadow_opacity);
|
||||
shadow = mix(half(1.0), sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth, taa_frame_count), half(omni_lights.data[idx].shadow_opacity));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -573,7 +582,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
vec3 color = omni_lights.data[idx].color;
|
||||
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
float transmittance_z = transmittance_depth; //no transmittance by default
|
||||
half transmittance_z = transmittance_depth; //no transmittance by default
|
||||
transmittance_color.a *= omni_attenuation;
|
||||
#ifndef SHADOWS_DISABLED
|
||||
if (omni_lights.data[idx].shadow_opacity > 0.001) {
|
||||
|
|
@ -586,7 +595,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
// Omni lights use direction.xy to store to store the offset between the two paraboloid regions
|
||||
vec2 flip_offset = omni_lights.data[idx].direction.xy;
|
||||
|
||||
vec3 local_vert = (omni_lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal) * omni_lights.data[idx].transmittance_bias, 1.0)).xyz;
|
||||
vec3 local_vert = (omni_lights.data[idx].shadow_matrix * vec4(vertex - normal * omni_lights.data[idx].transmittance_bias, 1.0)).xyz;
|
||||
|
||||
float shadow_len = length(local_vert); //need to remember shadow len from here
|
||||
vec3 shadow_sample = normalize(local_vert);
|
||||
|
|
@ -604,7 +613,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
pos = pos * 0.5 + 0.5;
|
||||
pos = uv_rect.xy + pos * uv_rect.zw;
|
||||
float shadow_z = textureLod(sampler2D(shadow_atlas, SAMPLER_LINEAR_CLAMP), pos, 0.0).r;
|
||||
transmittance_z = (depth - shadow_z) / omni_lights.data[idx].inv_radius;
|
||||
transmittance_z = half((depth - shadow_z) / omni_lights.data[idx].inv_radius);
|
||||
}
|
||||
#endif // !SHADOWS_DISABLED
|
||||
#endif // LIGHT_TRANSMITTANCE_USED
|
||||
|
|
@ -667,7 +676,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
}
|
||||
|
||||
vec3 light_rel_vec_norm = light_rel_vec / light_length;
|
||||
light_compute(normal, light_rel_vec_norm, eye_vec, size, color, false, omni_attenuation * shadow, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha, screen_uv, energy_compensation,
|
||||
light_compute(normal, hvec3(light_rel_vec_norm), eye_vec, size, hvec3(color), false, omni_attenuation * shadow, f0, roughness, metallic, half(omni_lights.data[idx].specular_amount), albedo, alpha, screen_uv, energy_compensation,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
|
|
@ -702,54 +711,53 @@ vec2 normal_to_panorama(vec3 n) {
|
|||
return panorama_coords;
|
||||
}
|
||||
|
||||
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float taa_frame_count, vec3 albedo, inout float alpha, vec2 screen_uv, vec3 energy_compensation,
|
||||
void light_process_spot(uint idx, vec3 vertex, hvec3 eye_vec, hvec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, hvec3 f0, half roughness, half metallic, float taa_frame_count, hvec3 albedo, inout half alpha, vec2 screen_uv, hvec3 energy_compensation,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
vec3 backlight,
|
||||
hvec3 backlight,
|
||||
#endif
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
vec4 transmittance_color,
|
||||
float transmittance_depth,
|
||||
float transmittance_boost,
|
||||
hvec4 transmittance_color,
|
||||
half transmittance_depth,
|
||||
half transmittance_boost,
|
||||
#endif
|
||||
#ifdef LIGHT_RIM_USED
|
||||
float rim, float rim_tint,
|
||||
half rim, half rim_tint,
|
||||
#endif
|
||||
#ifdef LIGHT_CLEARCOAT_USED
|
||||
float clearcoat, float clearcoat_roughness, vec3 vertex_normal,
|
||||
half clearcoat, half clearcoat_roughness, hvec3 vertex_normal,
|
||||
#endif
|
||||
#ifdef LIGHT_ANISOTROPY_USED
|
||||
vec3 binormal, vec3 tangent, float anisotropy,
|
||||
hvec3 binormal, hvec3 tangent, half anisotropy,
|
||||
#endif
|
||||
inout vec3 diffuse_light,
|
||||
inout vec3 specular_light) {
|
||||
const float EPSILON = 1e-6f;
|
||||
inout hvec3 diffuse_light,
|
||||
inout hvec3 specular_light) {
|
||||
|
||||
// Spot light attenuation.
|
||||
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
|
||||
float light_length = length(light_rel_vec);
|
||||
vec3 light_rel_vec_norm = light_rel_vec / light_length;
|
||||
float spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation);
|
||||
vec3 spot_dir = spot_lights.data[idx].direction;
|
||||
hvec3 light_rel_vec_norm = hvec3(light_rel_vec / light_length);
|
||||
half spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation);
|
||||
hvec3 spot_dir = hvec3(spot_lights.data[idx].direction);
|
||||
half cone_angle = half(spot_lights.data[idx].cone_angle);
|
||||
half scos = max(dot(-light_rel_vec_norm, spot_dir), cone_angle);
|
||||
|
||||
// This conversion to a highp float is crucial to prevent light leaking
|
||||
// due to precision errors in the following calculations (cone angle is mediump).
|
||||
highp float cone_angle = spot_lights.data[idx].cone_angle;
|
||||
float scos = max(dot(-light_rel_vec_norm, spot_dir), cone_angle);
|
||||
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cone_angle));
|
||||
spot_attenuation *= 1.0 - pow(spot_rim, spot_lights.data[idx].cone_attenuation);
|
||||
// This conversion to a highp float is crucial to prevent light leaking due to precision errors.
|
||||
float spot_rim = max(1e-4, float(half(1.0) - scos) / float(half(1.0) - cone_angle));
|
||||
spot_attenuation *= half(1.0 - pow(spot_rim, spot_lights.data[idx].cone_attenuation));
|
||||
|
||||
// Compute size.
|
||||
float size = 0.0;
|
||||
half size = half(0.0);
|
||||
if (sc_use_light_soft_shadows() && spot_lights.data[idx].size > 0.0) {
|
||||
float t = spot_lights.data[idx].size / max(0.001, light_length);
|
||||
size = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
|
||||
half t = half(spot_lights.data[idx].size / max(0.001, light_length));
|
||||
size = half(1.0) / sqrt(half(1.0) + t * t);
|
||||
size = max(half(1.0) - size, half(0.0));
|
||||
}
|
||||
|
||||
float shadow = 1.0;
|
||||
half shadow = half(1.0);
|
||||
#ifndef SHADOWS_DISABLED
|
||||
// Spot light shadow.
|
||||
if (spot_attenuation > EPSILON && spot_lights.data[idx].shadow_opacity > 0.001) {
|
||||
vec3 normal_bias = normal * light_length * spot_lights.data[idx].shadow_normal_bias * (1.0 - abs(dot(normal, light_rel_vec_norm)));
|
||||
if (spot_attenuation > HALF_FLT_MIN && spot_lights.data[idx].shadow_opacity > 0.001) {
|
||||
vec3 normal_bias = vec3(normal) * light_length * spot_lights.data[idx].shadow_normal_bias * (1.0 - abs(dot(normal, light_rel_vec_norm)));
|
||||
|
||||
//there is a shadowmap
|
||||
vec4 v = vec4(vertex + normal_bias, 1.0);
|
||||
|
|
@ -762,7 +770,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
//soft shadow
|
||||
|
||||
//find blocker
|
||||
float z_norm = dot(spot_dir, -light_rel_vec) * spot_lights.data[idx].inv_radius;
|
||||
float z_norm = dot(vec3(spot_dir), -light_rel_vec) * spot_lights.data[idx].inv_radius;
|
||||
|
||||
vec2 shadow_uv = splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy;
|
||||
|
||||
|
|
@ -797,39 +805,38 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
float penumbra = (-z_norm + blocker_average) / (1.0 - blocker_average);
|
||||
uv_size *= penumbra;
|
||||
|
||||
shadow = 0.0;
|
||||
shadow = half(0.0);
|
||||
|
||||
SPEC_CONSTANT_LOOP_ANNOTATION
|
||||
for (uint i = 0; i < sc_penumbra_shadow_samples(); i++) {
|
||||
vec2 suv = shadow_uv + (disk_rotation * scene_data_block.data.penumbra_shadow_kernel[i].xy) * uv_size;
|
||||
suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max);
|
||||
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, splane.z, 1.0));
|
||||
shadow += half(textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, splane.z, 1.0)));
|
||||
}
|
||||
|
||||
shadow /= float(sc_penumbra_shadow_samples());
|
||||
shadow = mix(1.0, shadow, spot_lights.data[idx].shadow_opacity);
|
||||
shadow /= half(sc_penumbra_shadow_samples());
|
||||
shadow = mix(half(1.0), shadow, half(spot_lights.data[idx].shadow_opacity));
|
||||
|
||||
} else {
|
||||
//no blockers found, so no shadow
|
||||
shadow = 1.0;
|
||||
shadow = half(1.0);
|
||||
}
|
||||
} else {
|
||||
//hard shadow
|
||||
vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z);
|
||||
shadow = mix(1.0, sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv, taa_frame_count), spot_lights.data[idx].shadow_opacity);
|
||||
shadow = mix(half(1.0), sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv, taa_frame_count), half(spot_lights.data[idx].shadow_opacity));
|
||||
}
|
||||
}
|
||||
#endif // SHADOWS_DISABLED
|
||||
|
||||
vec3 color = spot_lights.data[idx].color;
|
||||
float specular_amount = spot_lights.data[idx].specular_amount;
|
||||
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
float transmittance_z = transmittance_depth;
|
||||
half transmittance_z = transmittance_depth;
|
||||
transmittance_color.a *= spot_attenuation;
|
||||
#ifndef SHADOWS_DISABLED
|
||||
if (spot_lights.data[idx].shadow_opacity > 0.001) {
|
||||
vec4 splane = (spot_lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal) * spot_lights.data[idx].transmittance_bias, 1.0));
|
||||
vec4 splane = (spot_lights.data[idx].shadow_matrix * vec4(vertex - vec3(normal) * spot_lights.data[idx].transmittance_bias, 1.0));
|
||||
splane /= splane.w;
|
||||
|
||||
vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z);
|
||||
|
|
@ -841,8 +848,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
shadow_z = 2.0 * z_near * z_far / (z_far + z_near - shadow_z * (z_far - z_near));
|
||||
|
||||
//distance to light plane
|
||||
float z = dot(spot_dir, -light_rel_vec);
|
||||
transmittance_z = z - shadow_z;
|
||||
float z = dot(vec3(spot_dir), -light_rel_vec);
|
||||
transmittance_z = half(z - shadow_z);
|
||||
}
|
||||
#endif // !SHADOWS_DISABLED
|
||||
#endif // LIGHT_TRANSMITTANCE_USED
|
||||
|
|
@ -871,7 +878,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
}
|
||||
}
|
||||
|
||||
light_compute(normal, light_rel_vec_norm, eye_vec, size, color, false, spot_attenuation * shadow, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha, screen_uv, energy_compensation,
|
||||
light_compute(normal, hvec3(light_rel_vec_norm), eye_vec, size, hvec3(color), false, spot_attenuation * shadow, f0, roughness, metallic, half(spot_lights.data[idx].specular_amount), albedo, alpha, screen_uv, energy_compensation,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
|
|
@ -893,7 +900,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
diffuse_light, specular_light);
|
||||
}
|
||||
|
||||
void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) {
|
||||
void reflection_process(uint ref_index, vec3 vertex, hvec3 ref_vec, hvec3 normal, half roughness, hvec3 ambient_light, hvec3 specular_light, inout hvec4 ambient_accum, inout hvec4 reflection_accum) {
|
||||
vec3 box_extents = reflections.data[ref_index].box_extents;
|
||||
vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
|
||||
|
||||
|
|
@ -901,17 +908,16 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
|
|||
return;
|
||||
}
|
||||
|
||||
float blend = 1.0;
|
||||
half blend = half(1.0);
|
||||
if (reflections.data[ref_index].blend_distance != 0.0) {
|
||||
vec3 axis_blend_distance = min(vec3(reflections.data[ref_index].blend_distance), box_extents);
|
||||
vec3 blend_axes = abs(local_pos) - box_extents + axis_blend_distance;
|
||||
blend_axes /= axis_blend_distance;
|
||||
blend_axes = clamp(1.0 - blend_axes, vec3(0.0), vec3(1.0));
|
||||
|
||||
blend = pow(blend_axes.x * blend_axes.y * blend_axes.z, 2.0);
|
||||
vec3 blend_axes_highp = abs(local_pos) - box_extents + axis_blend_distance;
|
||||
hvec3 blend_axes = hvec3(blend_axes_highp / axis_blend_distance);
|
||||
blend_axes = clamp(half(1.0) - blend_axes, hvec3(0.0), hvec3(1.0));
|
||||
blend = pow(blend_axes.x * blend_axes.y * blend_axes.z, half(2.0));
|
||||
}
|
||||
|
||||
if (reflections.data[ref_index].intensity > 0.0 && reflection_accum.a < 1.0) { // compute reflection
|
||||
if (reflections.data[ref_index].intensity > 0.0 && reflection_accum.a < half(1.0)) { // compute reflection
|
||||
|
||||
vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
|
||||
|
||||
|
|
@ -928,20 +934,20 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
|
|||
local_ref_vec = posonbox - reflections.data[ref_index].box_offset;
|
||||
}
|
||||
|
||||
vec4 reflection;
|
||||
float reflection_blend = max(0.0, blend - reflection_accum.a);
|
||||
hvec4 reflection;
|
||||
half reflection_blend = max(half(0.0), blend - reflection_accum.a);
|
||||
|
||||
reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_ref_vec, reflections.data[ref_index].index), sqrt(roughness) * MAX_ROUGHNESS_LOD).rgb * sc_luminance_multiplier();
|
||||
reflection.rgb *= reflections.data[ref_index].exposure_normalization;
|
||||
reflection.rgb = hvec3(textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_ref_vec, reflections.data[ref_index].index), sqrt(roughness) * MAX_ROUGHNESS_LOD).rgb) * sc_luminance_multiplier();
|
||||
reflection.rgb *= half(reflections.data[ref_index].exposure_normalization);
|
||||
reflection.a = reflection_blend;
|
||||
|
||||
reflection.rgb *= reflections.data[ref_index].intensity;
|
||||
reflection.rgb *= half(reflections.data[ref_index].intensity);
|
||||
reflection.rgb *= reflection.a;
|
||||
|
||||
reflection_accum += reflection;
|
||||
}
|
||||
|
||||
if (ambient_accum.a >= 1.0) {
|
||||
if (ambient_accum.a >= half(1.0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -951,20 +957,20 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
|
|||
} break;
|
||||
case REFLECTION_AMBIENT_ENVIRONMENT: {
|
||||
vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
|
||||
vec4 ambient_out;
|
||||
float ambient_blend = max(0.0, blend - ambient_accum.a);
|
||||
hvec4 ambient_out;
|
||||
half ambient_blend = max(half(0.0), blend - ambient_accum.a);
|
||||
|
||||
ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb;
|
||||
ambient_out.rgb *= reflections.data[ref_index].exposure_normalization;
|
||||
ambient_out.rgb = hvec3(textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb);
|
||||
ambient_out.rgb *= half(reflections.data[ref_index].exposure_normalization);
|
||||
ambient_out.a = ambient_blend;
|
||||
ambient_out.rgb *= ambient_out.a;
|
||||
ambient_accum += ambient_out;
|
||||
} break;
|
||||
case REFLECTION_AMBIENT_COLOR: {
|
||||
vec4 ambient_out;
|
||||
float ambient_blend = max(0.0, blend - ambient_accum.a);
|
||||
hvec4 ambient_out;
|
||||
half ambient_blend = max(half(0.0), blend - ambient_accum.a);
|
||||
|
||||
ambient_out.rgb = reflections.data[ref_index].ambient;
|
||||
ambient_out.rgb = hvec3(reflections.data[ref_index].ambient);
|
||||
ambient_out.a = ambient_blend;
|
||||
ambient_out.rgb *= ambient_out.a;
|
||||
ambient_accum += ambient_out;
|
||||
|
|
@ -972,7 +978,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
|
|||
}
|
||||
}
|
||||
|
||||
float blur_shadow(float shadow) {
|
||||
half blur_shadow(half shadow) {
|
||||
return shadow;
|
||||
#if 0
|
||||
//disabling for now, will investigate later
|
||||
|
|
|
|||
|
|
@ -3,80 +3,81 @@
|
|||
// Eyeballed approximation of `exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25`.
|
||||
// Uses slightly more FMA instructions (2x rate) to avoid special instructions (0.25x rate).
|
||||
// Range is reduced to [0.64,4977] from [068,2,221,528] which makes mediump feasible for the rest of the shader.
|
||||
mediump float roughness_to_shininess(mediump float roughness) {
|
||||
mediump float r = 1.2 - roughness;
|
||||
mediump float r2 = r * r;
|
||||
return r * r2 * r2 * 2000.0;
|
||||
half roughness_to_shininess(half roughness) {
|
||||
half r = half(1.2) - roughness;
|
||||
half r2 = r * r;
|
||||
return r * r2 * r2 * half(2000.0);
|
||||
}
|
||||
|
||||
void light_compute_vertex(vec3 N, vec3 L, vec3 V, vec3 light_color, bool is_directional, float roughness,
|
||||
inout vec3 diffuse_light, inout vec3 specular_light) {
|
||||
float NdotL = min(dot(N, L), 1.0);
|
||||
float cNdotL = max(NdotL, 0.0); // clamped NdotL
|
||||
void light_compute_vertex(hvec3 N, hvec3 L, hvec3 V, hvec3 light_color, bool is_directional, half roughness,
|
||||
inout hvec3 diffuse_light, inout hvec3 specular_light) {
|
||||
half NdotL = min(dot(N, L), half(1.0));
|
||||
half cNdotL = max(NdotL, half(0.0)); // clamped NdotL
|
||||
|
||||
#if defined(DIFFUSE_LAMBERT_WRAP)
|
||||
// Energy conserving lambert wrap shader.
|
||||
// https://web.archive.org/web/20210228210901/http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/
|
||||
float diffuse_brdf_NL = max(0.0, (cNdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))) * (1.0 / M_PI);
|
||||
half diffuse_brdf_NL = max(half(0.0), (cNdotL + roughness) / ((half(1.0) + roughness) * (half(1.0) + roughness))) * half(1.0 / M_PI);
|
||||
#else
|
||||
// lambert
|
||||
float diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
|
||||
half diffuse_brdf_NL = cNdotL * half(1.0 / M_PI);
|
||||
#endif
|
||||
|
||||
diffuse_light += light_color * diffuse_brdf_NL;
|
||||
|
||||
#if !defined(SPECULAR_DISABLED)
|
||||
float specular_brdf_NL = 0.0;
|
||||
half specular_brdf_NL = half(0.0);
|
||||
// Normalized blinn always unless disabled.
|
||||
vec3 H = normalize(V + L);
|
||||
float cNdotH = clamp(dot(N, H), 0.0, 1.0);
|
||||
float shininess = roughness_to_shininess(roughness);
|
||||
float blinn = pow(cNdotH, shininess);
|
||||
blinn *= (shininess + 2.0) * (1.0 / (8.0 * M_PI)) * cNdotL;
|
||||
hvec3 H = normalize(V + L);
|
||||
half cNdotH = clamp(dot(N, H), half(0.0), half(1.0));
|
||||
half shininess = roughness_to_shininess(roughness);
|
||||
half blinn = pow(cNdotH, shininess);
|
||||
blinn *= (shininess + half(2.0)) * half(1.0 / (8.0 * M_PI)) * cNdotL;
|
||||
specular_brdf_NL = blinn;
|
||||
specular_light += specular_brdf_NL * light_color;
|
||||
#endif
|
||||
}
|
||||
|
||||
float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||
half 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);
|
||||
return half(nd * pow(max(distance, 0.0001), -decay));
|
||||
}
|
||||
|
||||
void light_process_omni_vertex(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness,
|
||||
inout vec3 diffuse_light, inout vec3 specular_light) {
|
||||
void light_process_omni_vertex(uint idx, vec3 vertex, hvec3 eye_vec, hvec3 normal, half roughness,
|
||||
inout hvec3 diffuse_light, inout hvec3 specular_light) {
|
||||
vec3 light_rel_vec = omni_lights.data[idx].position - vertex;
|
||||
float light_length = length(light_rel_vec);
|
||||
float omni_attenuation = get_omni_attenuation(light_length, omni_lights.data[idx].inv_radius, omni_lights.data[idx].attenuation);
|
||||
vec3 color = omni_lights.data[idx].color * omni_attenuation;
|
||||
hvec3 light_rel_vec_norm = hvec3(light_rel_vec / light_length);
|
||||
half omni_attenuation = get_omni_attenuation(light_length, omni_lights.data[idx].inv_radius, omni_lights.data[idx].attenuation);
|
||||
hvec3 color = hvec3(omni_lights.data[idx].color * omni_attenuation);
|
||||
|
||||
light_compute_vertex(normal, normalize(light_rel_vec), eye_vec, color, false, roughness,
|
||||
light_compute_vertex(normal, light_rel_vec_norm, eye_vec, color, false, roughness,
|
||||
diffuse_light,
|
||||
specular_light);
|
||||
}
|
||||
|
||||
void light_process_spot_vertex(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness,
|
||||
inout vec3 diffuse_light,
|
||||
inout vec3 specular_light) {
|
||||
void light_process_spot_vertex(uint idx, vec3 vertex, hvec3 eye_vec, hvec3 normal, half roughness,
|
||||
inout hvec3 diffuse_light,
|
||||
inout hvec3 specular_light) {
|
||||
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
|
||||
float light_length = length(light_rel_vec);
|
||||
float spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation);
|
||||
vec3 spot_dir = spot_lights.data[idx].direction;
|
||||
hvec3 light_rel_vec_norm = hvec3(light_rel_vec / light_length);
|
||||
half spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation);
|
||||
hvec3 spot_dir = hvec3(spot_lights.data[idx].direction);
|
||||
|
||||
// This conversion to a highp float is crucial to prevent light leaking
|
||||
// due to precision errors in the following calculations (cone angle is mediump).
|
||||
highp float cone_angle = spot_lights.data[idx].cone_angle;
|
||||
float scos = max(dot(-normalize(light_rel_vec), spot_dir), cone_angle);
|
||||
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cone_angle));
|
||||
half cone_angle = half(spot_lights.data[idx].cone_angle);
|
||||
half scos = max(dot(-light_rel_vec_norm, spot_dir), cone_angle);
|
||||
|
||||
spot_attenuation *= 1.0 - pow(spot_rim, spot_lights.data[idx].cone_attenuation);
|
||||
vec3 color = spot_lights.data[idx].color * spot_attenuation;
|
||||
float specular_amount = spot_lights.data[idx].specular_amount;
|
||||
// This conversion to a highp float is crucial to prevent light leaking due to precision errors.
|
||||
float spot_rim = max(1e-4, float(half(1.0) - scos) / float(half(1.0) - cone_angle));
|
||||
spot_attenuation *= half(1.0 - pow(spot_rim, spot_lights.data[idx].cone_attenuation));
|
||||
|
||||
light_compute_vertex(normal, normalize(light_rel_vec), eye_vec, color, false, roughness,
|
||||
hvec3 color = hvec3(spot_lights.data[idx].color * spot_attenuation);
|
||||
|
||||
light_compute_vertex(normal, light_rel_vec_norm, eye_vec, color, false, roughness,
|
||||
diffuse_light, specular_light);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -945,7 +945,7 @@ public:
|
|||
|
||||
enum Features {
|
||||
SUPPORTS_MULTIVIEW,
|
||||
SUPPORTS_FSR_HALF_FLOAT,
|
||||
SUPPORTS_HALF_FLOAT,
|
||||
SUPPORTS_ATTACHMENT_VRS,
|
||||
SUPPORTS_METALFX_SPATIAL,
|
||||
SUPPORTS_METALFX_TEMPORAL,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ public:
|
|||
FEATURE_ADVANCED_BIT = 1U << 0U,
|
||||
FEATURE_MULTIVIEW_BIT = 1U << 1U,
|
||||
FEATURE_VRS_BIT = 1U << 2U,
|
||||
FEATURE_FP16_BIT = 1U << 3U,
|
||||
FEATURE_FP32_BIT = 1U << 4U,
|
||||
};
|
||||
|
||||
// Used by the shader baker to globally enable features on all the shaders that will be exported.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue