123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602 |
- #[vertex]
- #version 450
- #VERSION_DEFINES
- /* Include our forward mobile UBOs definitions etc. */
- #include "scene_forward_mobile_inc.glsl"
- #define SHADER_IS_SRGB false
- /* INPUT ATTRIBS */
- layout(location = 0) in vec3 vertex_attrib;
- //only for pure render depth when normal is not used
- #ifdef NORMAL_USED
- layout(location = 1) in vec3 normal_attrib;
- #endif
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- layout(location = 2) in vec4 tangent_attrib;
- #endif
- #if defined(COLOR_USED)
- layout(location = 3) in vec4 color_attrib;
- #endif
- #ifdef UV_USED
- layout(location = 4) in vec2 uv_attrib;
- #endif
- #if defined(UV2_USED) || defined(USE_LIGHTMAP) || defined(MODE_RENDER_MATERIAL)
- layout(location = 5) in vec2 uv2_attrib;
- #endif // MODE_RENDER_MATERIAL
- #if defined(CUSTOM0_USED)
- layout(location = 6) in vec4 custom0_attrib;
- #endif
- #if defined(CUSTOM1_USED)
- layout(location = 7) in vec4 custom1_attrib;
- #endif
- #if defined(CUSTOM2_USED)
- layout(location = 8) in vec4 custom2_attrib;
- #endif
- #if defined(CUSTOM3_USED)
- layout(location = 9) in vec4 custom3_attrib;
- #endif
- #if defined(BONES_USED) || defined(USE_PARTICLE_TRAILS)
- layout(location = 10) in uvec4 bone_attrib;
- #endif
- #if defined(WEIGHTS_USED) || defined(USE_PARTICLE_TRAILS)
- layout(location = 11) in vec4 weight_attrib;
- #endif
- /* Varyings */
- layout(location = 0) highp out vec3 vertex_interp;
- #ifdef NORMAL_USED
- layout(location = 1) mediump out vec3 normal_interp;
- #endif
- #if defined(COLOR_USED)
- layout(location = 2) mediump out vec4 color_interp;
- #endif
- #ifdef UV_USED
- layout(location = 3) mediump out vec2 uv_interp;
- #endif
- #if defined(UV2_USED) || defined(USE_LIGHTMAP)
- layout(location = 4) mediump out vec2 uv2_interp;
- #endif
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- layout(location = 5) mediump out vec3 tangent_interp;
- layout(location = 6) mediump out vec3 binormal_interp;
- #endif
- #ifdef MATERIAL_UNIFORMS_USED
- layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{
- #MATERIAL_UNIFORMS
- } material;
- #endif
- #ifdef MODE_DUAL_PARABOLOID
- layout(location = 8) out highp float dp_clip;
- #endif
- #ifdef USE_MULTIVIEW
- #ifdef has_VK_KHR_multiview
- #define ViewIndex gl_ViewIndex
- #else
- // !BAS! This needs to become an input once we implement our fallback!
- #define ViewIndex 0
- #endif
- #else
- // Set to zero, not supported in non stereo
- #define ViewIndex 0
- #endif //USE_MULTIVIEW
- invariant gl_Position;
- #GLOBALS
- void main() {
- vec4 instance_custom = vec4(0.0);
- #if defined(COLOR_USED)
- color_interp = color_attrib;
- #endif
- bool is_multimesh = bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH);
- mat4 model_matrix = draw_call.transform;
- mat3 model_normal_matrix;
- if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
- model_normal_matrix = transpose(inverse(mat3(model_matrix)));
- } else {
- model_normal_matrix = mat3(model_matrix);
- }
- if (is_multimesh) {
- //multimesh, instances are for it
- mat4 matrix;
- #ifdef USE_PARTICLE_TRAILS
- uint trail_size = (draw_call.flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK;
- uint stride = 3 + 1 + 1; //particles always uses this format
- uint offset = trail_size * stride * gl_InstanceIndex;
- #ifdef COLOR_USED
- vec4 pcolor;
- #endif
- {
- uint boffset = offset + bone_attrib.x * stride;
- matrix = mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], transforms.data[boffset + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weight_attrib.x;
- #ifdef COLOR_USED
- pcolor = transforms.data[boffset + 3] * weight_attrib.x;
- #endif
- }
- if (weight_attrib.y > 0.001) {
- uint boffset = offset + bone_attrib.y * stride;
- matrix += mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], transforms.data[boffset + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weight_attrib.y;
- #ifdef COLOR_USED
- pcolor += transforms.data[boffset + 3] * weight_attrib.y;
- #endif
- }
- if (weight_attrib.z > 0.001) {
- uint boffset = offset + bone_attrib.z * stride;
- matrix += mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], transforms.data[boffset + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weight_attrib.z;
- #ifdef COLOR_USED
- pcolor += transforms.data[boffset + 3] * weight_attrib.z;
- #endif
- }
- if (weight_attrib.w > 0.001) {
- uint boffset = offset + bone_attrib.w * stride;
- matrix += mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], transforms.data[boffset + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weight_attrib.w;
- #ifdef COLOR_USED
- pcolor += transforms.data[boffset + 3] * weight_attrib.w;
- #endif
- }
- instance_custom = transforms.data[offset + 4];
- #ifdef COLOR_USED
- color_interp *= pcolor;
- #endif
- #else
- uint stride = 0;
- {
- //TODO implement a small lookup table for the stride
- if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
- stride += 2;
- } else {
- stride += 3;
- }
- if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
- stride += 1;
- }
- if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
- stride += 1;
- }
- }
- uint offset = stride * gl_InstanceIndex;
- if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
- matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
- offset += 2;
- } else {
- matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], transforms.data[offset + 2], vec4(0.0, 0.0, 0.0, 1.0));
- offset += 3;
- }
- if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
- #ifdef COLOR_USED
- color_interp *= transforms.data[offset];
- #endif
- offset += 1;
- }
- if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
- instance_custom = transforms.data[offset];
- }
- #endif
- //transpose
- matrix = transpose(matrix);
- model_matrix = model_matrix * matrix;
- model_normal_matrix = model_normal_matrix * mat3(matrix);
- }
- vec3 vertex = vertex_attrib;
- #ifdef NORMAL_USED
- vec3 normal = normal_attrib * 2.0 - 1.0;
- #endif
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
- float binormalf = tangent_attrib.a * 2.0 - 1.0;
- vec3 binormal = normalize(cross(normal, tangent) * binormalf);
- #endif
- #ifdef UV_USED
- uv_interp = uv_attrib;
- #endif
- #if defined(UV2_USED) || defined(USE_LIGHTMAP)
- uv2_interp = uv2_attrib;
- #endif
- #ifdef OVERRIDE_POSITION
- vec4 position;
- #endif
- #ifdef USE_MULTIVIEW
- mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex];
- mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex];
- #else
- mat4 projection_matrix = scene_data.projection_matrix;
- mat4 inv_projection_matrix = scene_data.inv_projection_matrix;
- #endif //USE_MULTIVIEW
- //using world coordinates
- #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
- vertex = (model_matrix * vec4(vertex, 1.0)).xyz;
- #ifdef NORMAL_USED
- normal = model_normal_matrix * normal;
- #endif
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- tangent = model_normal_matrix * tangent;
- binormal = model_normal_matrix * binormal;
- #endif
- #endif
- float roughness = 1.0;
- mat4 modelview = scene_data.view_matrix * model_matrix;
- mat3 modelview_normal = mat3(scene_data.view_matrix) * model_normal_matrix;
- {
- #CODE : VERTEX
- }
- /* output */
- // using local coordinates (default)
- #if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED)
- vertex = (modelview * vec4(vertex, 1.0)).xyz;
- #ifdef NORMAL_USED
- normal = modelview_normal * normal;
- #endif
- #endif
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- binormal = modelview_normal * binormal;
- tangent = modelview_normal * tangent;
- #endif
- //using world coordinates
- #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
- vertex = (scene_data.view_matrix * vec4(vertex, 1.0)).xyz;
- #ifdef NORMAL_USED
- normal = (scene_data.view_matrix * vec4(normal, 0.0)).xyz;
- #endif
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- binormal = (scene_data.view_matrix * vec4(binormal, 0.0)).xyz;
- tangent = (scene_data.view_matrix * vec4(tangent, 0.0)).xyz;
- #endif
- #endif
- vertex_interp = vertex;
- #ifdef NORMAL_USED
- normal_interp = normal;
- #endif
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- tangent_interp = tangent;
- binormal_interp = binormal;
- #endif
- #ifdef MODE_RENDER_DEPTH
- #ifdef MODE_DUAL_PARABOLOID
- vertex_interp.z *= scene_data.dual_paraboloid_side;
- dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias
- //for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
- vec3 vtx = vertex_interp;
- float distance = length(vtx);
- vtx = normalize(vtx);
- vtx.xy /= 1.0 - vtx.z;
- vtx.z = (distance / scene_data.z_far);
- vtx.z = vtx.z * 2.0 - 1.0;
- vertex_interp = vtx;
- #endif
- #endif //MODE_RENDER_DEPTH
- #ifdef OVERRIDE_POSITION
- gl_Position = position;
- #else
- gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
- #endif // OVERRIDE_POSITION
- #ifdef MODE_RENDER_DEPTH
- if (scene_data.pancake_shadows) {
- if (gl_Position.z <= 0.00001) {
- gl_Position.z = 0.00001;
- }
- }
- #endif // MODE_RENDER_DEPTH
- #ifdef MODE_RENDER_MATERIAL
- if (scene_data.material_uv2_mode) {
- vec2 uv_offset = draw_call.lightmap_uv_scale.xy; // we are abusing lightmap_uv_scale here, we shouldn't have a lightmap during a depth pass...
- gl_Position.xy = (uv2_attrib.xy + uv_offset) * 2.0 - 1.0;
- gl_Position.z = 0.00001;
- gl_Position.w = 1.0;
- }
- #endif // MODE_RENDER_MATERIAL
- }
- #[fragment]
- #version 450
- #VERSION_DEFINES
- #define SHADER_IS_SRGB false
- /* Specialization Constants */
- #if !defined(MODE_RENDER_DEPTH)
- #if !defined(MODE_UNSHADED)
- layout(constant_id = 0) const bool sc_use_light_projector = false;
- layout(constant_id = 1) const bool sc_use_light_soft_shadows = false;
- layout(constant_id = 2) const bool sc_use_directional_soft_shadows = false;
- layout(constant_id = 3) const uint sc_soft_shadow_samples = 4;
- layout(constant_id = 4) const uint sc_penumbra_shadow_samples = 4;
- layout(constant_id = 5) const uint sc_directional_soft_shadow_samples = 4;
- layout(constant_id = 6) const uint sc_directional_penumbra_shadow_samples = 4;
- layout(constant_id = 8) const bool sc_projector_use_mipmaps = true;
- layout(constant_id = 9) const bool sc_disable_omni_lights = false;
- layout(constant_id = 10) const bool sc_disable_spot_lights = false;
- layout(constant_id = 11) const bool sc_disable_reflection_probes = false;
- layout(constant_id = 12) const bool sc_disable_directional_lights = false;
- #endif //!MODE_UNSHADED
- layout(constant_id = 7) const bool sc_decal_use_mipmaps = true;
- layout(constant_id = 13) const bool sc_disable_decals = false;
- layout(constant_id = 14) const bool sc_disable_fog = false;
- #endif //!MODE_RENDER_DEPTH
- layout(constant_id = 15) const float sc_luminance_multiplier = 2.0;
- /* Include our forward mobile UBOs definitions etc. */
- #include "scene_forward_mobile_inc.glsl"
- /* Varyings */
- layout(location = 0) highp in vec3 vertex_interp;
- #ifdef NORMAL_USED
- layout(location = 1) mediump in vec3 normal_interp;
- #endif
- #if defined(COLOR_USED)
- layout(location = 2) mediump in vec4 color_interp;
- #endif
- #ifdef UV_USED
- layout(location = 3) mediump in vec2 uv_interp;
- #endif
- #if defined(UV2_USED) || defined(USE_LIGHTMAP)
- layout(location = 4) mediump in vec2 uv2_interp;
- #endif
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- layout(location = 5) mediump in vec3 tangent_interp;
- layout(location = 6) mediump in vec3 binormal_interp;
- #endif
- #ifdef MODE_DUAL_PARABOLOID
- layout(location = 8) highp in float dp_clip;
- #endif
- #ifdef USE_MULTIVIEW
- #ifdef has_VK_KHR_multiview
- #define ViewIndex gl_ViewIndex
- #else
- // !BAS! This needs to become an input once we implement our fallback!
- #define ViewIndex 0
- #endif
- #else
- // Set to zero, not supported in non stereo
- #define ViewIndex 0
- #endif //USE_MULTIVIEW
- //defines to keep compatibility with vertex
- #define model_matrix draw_call.transform
- #ifdef USE_MULTIVIEW
- #define projection_matrix scene_data.projection_matrix_view[ViewIndex]
- #else
- #define projection_matrix scene_data.projection_matrix
- #endif
- #if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
- //both required for transmittance to be enabled
- #define LIGHT_TRANSMITTANCE_USED
- #endif
- #ifdef MATERIAL_UNIFORMS_USED
- layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{
- #MATERIAL_UNIFORMS
- } material;
- #endif
- #GLOBALS
- /* clang-format on */
- #ifdef MODE_RENDER_DEPTH
- #ifdef MODE_RENDER_MATERIAL
- layout(location = 0) out vec4 albedo_output_buffer;
- layout(location = 1) out vec4 normal_output_buffer;
- layout(location = 2) out vec4 orm_output_buffer;
- layout(location = 3) out vec4 emission_output_buffer;
- layout(location = 4) out float depth_output_buffer;
- #endif // MODE_RENDER_MATERIAL
- #else // RENDER DEPTH
- #ifdef MODE_MULTIPLE_RENDER_TARGETS
- layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness
- layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter)
- #else
- layout(location = 0) out mediump vec4 frag_color;
- #endif // MODE_MULTIPLE_RENDER_TARGETS
- #endif // RENDER DEPTH
- #include "scene_forward_aa_inc.glsl"
- #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
- // Default to SPECULAR_SCHLICK_GGX.
- #if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_TOON)
- #define SPECULAR_SCHLICK_GGX
- #endif
- #include "scene_forward_lights_inc.glsl"
- #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
- #ifndef MODE_RENDER_DEPTH
- /*
- Only supporting normal fog here.
- */
- vec4 fog_process(vec3 vertex) {
- vec3 fog_color = scene_data.fog_light_color;
- if (scene_data.fog_aerial_perspective > 0.0) {
- vec3 sky_fog_color = vec3(0.0);
- vec3 cube_view = scene_data.radiance_inverse_xform * vertex;
- // mip_level always reads from the second mipmap and higher so the fog is always slightly blurred
- float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near));
- #ifdef USE_RADIANCE_CUBEMAP_ARRAY
- float lod, blend;
- blend = modf(mip_level * MAX_ROUGHNESS_LOD, lod);
- sky_fog_color = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(cube_view, lod)).rgb;
- sky_fog_color = mix(sky_fog_color, texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(cube_view, lod + 1)).rgb, blend);
- #else
- sky_fog_color = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_view, mip_level * MAX_ROUGHNESS_LOD).rgb;
- #endif //USE_RADIANCE_CUBEMAP_ARRAY
- fog_color = mix(fog_color, sky_fog_color, scene_data.fog_aerial_perspective);
- }
- if (scene_data.fog_sun_scatter > 0.001) {
- vec4 sun_scatter = vec4(0.0);
- float sun_total = 0.0;
- vec3 view = normalize(vertex);
- for (uint i = 0; i < scene_data.directional_light_count; i++) {
- vec3 light_color = directional_lights.data[i].color * directional_lights.data[i].energy;
- float light_amount = pow(max(dot(view, directional_lights.data[i].direction), 0.0), 8.0);
- fog_color += light_color * light_amount * scene_data.fog_sun_scatter;
- }
- }
- float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
- if (abs(scene_data.fog_height_density) >= 0.0001) {
- float y = (scene_data.inv_view_matrix * vec4(vertex, 1.0)).y;
- float y_dist = y - scene_data.fog_height;
- float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density));
- fog_amount = max(vfog_amount, fog_amount);
- }
- return vec4(fog_color, fog_amount);
- }
- #endif //!MODE_RENDER DEPTH
- void main() {
- #ifdef MODE_DUAL_PARABOLOID
- if (dp_clip > 0.0)
- discard;
- #endif
- //lay out everything, whatever is unused is optimized away anyway
- vec3 vertex = vertex_interp;
- vec3 view = -normalize(vertex_interp);
- vec3 albedo = vec3(1.0);
- vec3 backlight = vec3(0.0);
- vec4 transmittance_color = vec4(0.0);
- float transmittance_depth = 0.0;
- float transmittance_boost = 0.0;
- float metallic = 0.0;
- float specular = 0.5;
- vec3 emission = vec3(0.0);
- float roughness = 1.0;
- float rim = 0.0;
- float rim_tint = 0.0;
- float clearcoat = 0.0;
- float clearcoat_roughness = 0.0;
- float anisotropy = 0.0;
- vec2 anisotropy_flow = vec2(1.0, 0.0);
- vec4 fog = vec4(0.0);
- #if defined(CUSTOM_RADIANCE_USED)
- vec4 custom_radiance = vec4(0.0);
- #endif
- #if defined(CUSTOM_IRRADIANCE_USED)
- vec4 custom_irradiance = vec4(0.0);
- #endif
- float ao = 1.0;
- float ao_light_affect = 0.0;
- float alpha = 1.0;
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec3 binormal = normalize(binormal_interp);
- vec3 tangent = normalize(tangent_interp);
- #else
- vec3 binormal = vec3(0.0);
- vec3 tangent = vec3(0.0);
- #endif
- #ifdef NORMAL_USED
- vec3 normal = normalize(normal_interp);
- #if defined(DO_SIDE_CHECK)
- if (!gl_FrontFacing) {
- normal = -normal;
- }
- #endif
- #endif //NORMAL_USED
- #ifdef UV_USED
- vec2 uv = uv_interp;
- #endif
- #if defined(UV2_USED) || defined(USE_LIGHTMAP)
- vec2 uv2 = uv2_interp;
- #endif
- #if defined(COLOR_USED)
- vec4 color = color_interp;
- #endif
- #if defined(NORMAL_MAP_USED)
- vec3 normal_map = vec3(0.5);
- #endif
- float normal_map_depth = 1.0;
- vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center
- float sss_strength = 0.0;
- #ifdef ALPHA_SCISSOR_USED
- float alpha_scissor_threshold = 1.0;
- #endif // ALPHA_SCISSOR_USED
- #ifdef ALPHA_HASH_USED
- float alpha_hash_scale = 1.0;
- #endif // ALPHA_HASH_USED
- #ifdef ALPHA_ANTIALIASING_EDGE_USED
- float alpha_antialiasing_edge = 0.0;
- vec2 alpha_texture_coordinate = vec2(0.0, 0.0);
- #endif // ALPHA_ANTIALIASING_EDGE_USED
- {
- #CODE : FRAGMENT
- }
- #ifdef LIGHT_TRANSMITTANCE_USED
- #ifdef SSS_MODE_SKIN
- transmittance_color.a = sss_strength;
- #else
- transmittance_color.a *= sss_strength;
- #endif
- #endif
- #ifndef USE_SHADOW_TO_OPACITY
- #ifdef ALPHA_SCISSOR_USED
- if (alpha < alpha_scissor_threshold) {
- discard;
- }
- #endif // ALPHA_SCISSOR_USED
- // alpha hash can be used in unison with alpha antialiasing
- #ifdef ALPHA_HASH_USED
- if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) {
- discard;
- }
- #endif // ALPHA_HASH_USED
- // If we are not edge antialiasing, we need to remove the output alpha channel from scissor and hash
- #if (defined(ALPHA_SCISSOR_USED) || defined(ALPHA_HASH_USED)) && !defined(ALPHA_ANTIALIASING_EDGE_USED)
- alpha = 1.0;
- #endif
- #ifdef ALPHA_ANTIALIASING_EDGE_USED
- // If alpha scissor is used, we must further the edge threshold, otherwise we won't get any edge feather
- #ifdef ALPHA_SCISSOR_USED
- alpha_antialiasing_edge = clamp(alpha_scissor_threshold + alpha_antialiasing_edge, 0.0, 1.0);
- #endif
- alpha = compute_alpha_antialiasing_edge(alpha, alpha_texture_coordinate, alpha_antialiasing_edge);
- #endif // ALPHA_ANTIALIASING_EDGE_USED
- #ifdef USE_OPAQUE_PREPASS
- if (alpha < scene_data.opaque_prepass_threshold) {
- discard;
- }
- #endif // USE_OPAQUE_PREPASS
- #endif // !USE_SHADOW_TO_OPACITY
- #ifdef NORMAL_MAP_USED
- normal_map.xy = normal_map.xy * 2.0 - 1.0;
- normal_map.z = sqrt(max(0.0, 1.0 - dot(normal_map.xy, normal_map.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc.
- normal = normalize(mix(normal, tangent * normal_map.x + binormal * normal_map.y + normal * normal_map.z, normal_map_depth));
- #endif
- #ifdef LIGHT_ANISOTROPY_USED
- if (anisotropy > 0.01) {
- //rotation matrix
- mat3 rot = mat3(tangent, binormal, normal);
- //make local to space
- tangent = normalize(rot * vec3(anisotropy_flow.x, anisotropy_flow.y, 0.0));
- binormal = normalize(rot * vec3(-anisotropy_flow.y, anisotropy_flow.x, 0.0));
- }
- #endif
- #ifdef ENABLE_CLIP_ALPHA
- if (albedo.a < 0.99) {
- //used for doublepass and shadowmapping
- discard;
- }
- #endif
- /////////////////////// FOG //////////////////////
- #ifndef MODE_RENDER_DEPTH
- #ifndef CUSTOM_FOG_USED
- // fog must be processed as early as possible and then packed.
- // to maximize VGPR usage
- // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
- if (!sc_disable_fog && scene_data.fog_enabled) {
- fog = fog_process(vertex);
- }
- #endif //!CUSTOM_FOG_USED
- uint fog_rg = packHalf2x16(fog.rg);
- uint fog_ba = packHalf2x16(fog.ba);
- #endif //!MODE_RENDER_DEPTH
- /////////////////////// DECALS ////////////////////////////////
- #ifndef MODE_RENDER_DEPTH
- vec3 vertex_ddx = dFdx(vertex);
- vec3 vertex_ddy = dFdy(vertex);
- if (!sc_disable_decals) { //Decals
- // must implement
- uint decal_indices = draw_call.decals.x;
- for (uint i = 0; i < 8; i++) {
- uint decal_index = decal_indices & 0xFF;
- if (i == 4) {
- decal_indices = draw_call.decals.y;
- } else {
- decal_indices = decal_indices >> 8;
- }
- if (decal_index == 0xFF) {
- break;
- }
- vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
- if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
- continue; //out of decal
- }
- float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
- if (decals.data[decal_index].normal_fade > 0.0) {
- fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
- }
- //we need ddx/ddy for mipmaps, so simulate them
- vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
- vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
- if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
- //has albedo
- vec4 decal_albedo;
- if (sc_decal_use_mipmaps) {
- decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
- } else {
- decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0);
- }
- decal_albedo *= decals.data[decal_index].modulate;
- decal_albedo.a *= fade;
- albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
- if (decals.data[decal_index].normal_rect != vec4(0.0)) {
- vec3 decal_normal;
- if (sc_decal_use_mipmaps) {
- decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
- } else {
- decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz;
- }
- decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
- decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
- //convert to view space, use xzy because y is up
- decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz;
- normal = normalize(mix(normal, decal_normal, decal_albedo.a));
- }
- if (decals.data[decal_index].orm_rect != vec4(0.0)) {
- vec3 decal_orm;
- if (sc_decal_use_mipmaps) {
- decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
- } else {
- decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz;
- }
- ao = mix(ao, decal_orm.r, decal_albedo.a);
- roughness = mix(roughness, decal_orm.g, decal_albedo.a);
- metallic = mix(metallic, decal_orm.b, decal_albedo.a);
- }
- }
- if (decals.data[decal_index].emission_rect != vec4(0.0)) {
- //emission is additive, so its independent from albedo
- if (sc_decal_use_mipmaps) {
- emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
- } else {
- emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade;
- }
- }
- }
- } //Decals
- #endif //!MODE_RENDER_DEPTH
- /////////////////////// LIGHTING //////////////////////////////
- #ifdef NORMAL_USED
- if (scene_data.roughness_limiter_enabled) {
- //https://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
- float roughness2 = roughness * roughness;
- vec3 dndu = dFdx(normal), dndv = dFdy(normal);
- float variance = scene_data.roughness_limiter_amount * (dot(dndu, dndu) + dot(dndv, dndv));
- float kernelRoughness2 = min(2.0 * variance, scene_data.roughness_limiter_limit); //limit effect
- float filteredRoughness2 = min(1.0, roughness2 + kernelRoughness2);
- roughness = sqrt(filteredRoughness2);
- }
- #endif // NORMAL_USED
- //apply energy conservation
- vec3 specular_light = vec3(0.0, 0.0, 0.0);
- vec3 diffuse_light = vec3(0.0, 0.0, 0.0);
- vec3 ambient_light = vec3(0.0, 0.0, 0.0);
- #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
- if (scene_data.use_reflection_cubemap) {
- #ifdef LIGHT_ANISOTROPY_USED
- // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
- vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
- vec3 anisotropic_tangent = cross(anisotropic_direction, view);
- vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
- vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
- vec3 ref_vec = reflect(-view, bent_normal);
- #else
- vec3 ref_vec = reflect(-view, normal);
- #endif
- float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
- ref_vec = scene_data.radiance_inverse_xform * ref_vec;
- #ifdef USE_RADIANCE_CUBEMAP_ARRAY
- float lod, blend;
- blend = modf(roughness * MAX_ROUGHNESS_LOD, lod);
- specular_light = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod)).rgb;
- specular_light = mix(specular_light, texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod + 1)).rgb, blend);
- #else // USE_RADIANCE_CUBEMAP_ARRAY
- specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
- #endif //USE_RADIANCE_CUBEMAP_ARRAY
- specular_light *= horizon * horizon;
- specular_light *= scene_data.ambient_light_color_energy.a;
- }
- #if defined(CUSTOM_RADIANCE_USED)
- specular_light = mix(specular_light, custom_radiance.rgb, custom_radiance.a);
- #endif // CUSTOM_RADIANCE_USED
- #ifndef USE_LIGHTMAP
- //lightmap overrides everything
- if (scene_data.use_ambient_light) {
- ambient_light = scene_data.ambient_light_color_energy.rgb;
- if (scene_data.use_ambient_cubemap) {
- vec3 ambient_dir = scene_data.radiance_inverse_xform * normal;
- #ifdef USE_RADIANCE_CUBEMAP_ARRAY
- vec3 cubemap_ambient = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ambient_dir, MAX_ROUGHNESS_LOD)).rgb;
- #else
- vec3 cubemap_ambient = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ambient_dir, MAX_ROUGHNESS_LOD).rgb;
- #endif //USE_RADIANCE_CUBEMAP_ARRAY
- ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix);
- }
- }
- #endif // !USE_LIGHTMAP
- #if defined(CUSTOM_IRRADIANCE_USED)
- ambient_light = mix(specular_light, custom_irradiance.rgb, custom_irradiance.a);
- #endif // CUSTOM_IRRADIANCE_USED
- #ifdef LIGHT_CLEARCOAT_USED
- if (scene_data.use_reflection_cubemap) {
- vec3 n = normalize(normal_interp); // We want to use geometric normal, not normal_map
- float NoV = max(dot(n, view), 0.0001);
- vec3 ref_vec = reflect(-view, n);
- // The clear coat layer assumes an IOR of 1.5 (4% reflectance)
- float Fc = clearcoat * (0.04 + 0.96 * SchlickFresnel(NoV));
- float attenuation = 1.0 - Fc;
- ambient_light *= attenuation;
- specular_light *= attenuation;
- float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
- ref_vec = scene_data.radiance_inverse_xform * ref_vec;
- float roughness_lod = mix(0.001, 0.1, clearcoat_roughness) * MAX_ROUGHNESS_LOD;
- #ifdef USE_RADIANCE_CUBEMAP_ARRAY
- float lod, blend;
- blend = modf(roughness_lod, lod);
- vec3 clearcoat_light = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod)).rgb;
- clearcoat_light = mix(clearcoat_light, texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod + 1)).rgb, blend);
- #else
- vec3 clearcoat_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness_lod).rgb;
- #endif //USE_RADIANCE_CUBEMAP_ARRAY
- specular_light += clearcoat_light * horizon * horizon * Fc * scene_data.ambient_light_color_energy.a;
- }
- #endif
- #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
- //radiance
- #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
- #ifdef USE_LIGHTMAP
- //lightmap
- if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
- uint index = draw_call.gi_offset;
- vec3 wnormal = mat3(scene_data.inv_view_matrix) * normal;
- const float c1 = 0.429043;
- const float c2 = 0.511664;
- const float c3 = 0.743125;
- const float c4 = 0.886227;
- const float c5 = 0.247708;
- ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
- c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
- c4 * lightmap_captures.data[index].sh[0].rgb -
- c5 * lightmap_captures.data[index].sh[6].rgb +
- 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
- 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
- 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
- 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
- 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
- 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
- } else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
- bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
- uint ofs = draw_call.gi_offset & 0xFFFF;
- vec3 uvw;
- uvw.xy = uv2 * draw_call.lightmap_uv_scale.zw + draw_call.lightmap_uv_scale.xy;
- uvw.z = float((draw_call.gi_offset >> 16) & 0xFFFF);
- if (uses_sh) {
- uvw.z *= 4.0; //SH textures use 4 times more data
- vec3 lm_light_l0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb;
- vec3 lm_light_l1n1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 1.0), 0.0).rgb;
- vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
- vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
- uint idx = draw_call.gi_offset >> 20;
- vec3 n = normalize(lightmaps.data[idx].normal_xform * normal);
- ambient_light += lm_light_l0 * 0.282095f;
- ambient_light += lm_light_l1n1 * 0.32573 * n.y;
- ambient_light += lm_light_l1_0 * 0.32573 * n.z;
- ambient_light += lm_light_l1p1 * 0.32573 * n.x;
- if (metallic > 0.01) { // since the more direct bounced light is lost, we can kind of fake it with this trick
- vec3 r = reflect(normalize(-vertex), normal);
- specular_light += lm_light_l1n1 * 0.32573 * r.y;
- specular_light += lm_light_l1_0 * 0.32573 * r.z;
- specular_light += lm_light_l1p1 * 0.32573 * r.x;
- }
- } else {
- ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb;
- }
- }
- // No GI nor non low end mode...
- #endif // USE_LIGHTMAP
- // skipping ssao, do we remove ssao totally?
- if (!sc_disable_reflection_probes) { //Reflection probes
- vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
- vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
- uint reflection_indices = draw_call.reflection_probes.x;
- for (uint i = 0; i < 8; i++) {
- uint reflection_index = reflection_indices & 0xFF;
- if (i == 4) {
- reflection_indices = draw_call.reflection_probes.y;
- } else {
- reflection_indices = reflection_indices >> 8;
- }
- if (reflection_index == 0xFF) {
- break;
- }
- #ifdef LIGHT_ANISOTROPY_USED
- // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
- vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
- vec3 anisotropic_tangent = cross(anisotropic_direction, view);
- vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
- vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
- #else
- vec3 bent_normal = normal;
- #endif
- reflection_process(reflection_index, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
- }
- if (reflection_accum.a > 0.0) {
- specular_light = reflection_accum.rgb / reflection_accum.a;
- }
- #if !defined(USE_LIGHTMAP)
- if (ambient_accum.a > 0.0) {
- ambient_light = ambient_accum.rgb / ambient_accum.a;
- }
- #endif
- } //Reflection probes
- // finalize ambient light here
- ambient_light *= albedo.rgb;
- ambient_light *= ao;
- // convert ao to direct light ao
- ao = mix(1.0, ao, ao_light_affect);
- //this saves some VGPRs
- vec3 f0 = F0(metallic, specular, albedo);
- {
- #if defined(DIFFUSE_TOON)
- //simplify for toon, as
- specular_light *= specular * metallic * albedo * 2.0;
- #else
- // scales the specular reflections, needs to be computed before lighting happens,
- // but after environment, GI, and reflection probes are added
- // Environment brdf approximation (Lazarov 2013)
- // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
- const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
- const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
- vec4 r = roughness * c0 + c1;
- float ndotv = clamp(dot(normal, view), 0.0, 1.0);
- float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
- vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
- specular_light *= env.x * f0 + env.y;
- #endif
- }
- #endif // !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)
- if (!sc_disable_directional_lights) { //directional light
- #ifndef SHADOWS_DISABLED
- // Do shadow and lighting in two passes to reduce register pressure
- uint shadow0 = 0;
- uint shadow1 = 0;
- for (uint i = 0; i < 8; i++) {
- if (i >= scene_data.directional_light_count) {
- break;
- }
- if (!bool(directional_lights.data[i].mask & draw_call.layer_mask)) {
- continue; //not masked
- }
- float shadow = 1.0;
- // Directional light shadow code is basically the same as forward clustered at this point in time minus `LIGHT_TRANSMITTANCE_USED` support.
- // Not sure if there is a reason to change this seeing directional lights are part of our global data
- // Should think about whether we may want to move this code into an include file or function??
- #ifdef USE_SOFT_SHADOWS
- //version with soft shadows, more expensive
- if (directional_lights.data[i].shadow_enabled) {
- float depth_z = -vertex.z;
- vec4 pssm_coord;
- vec3 light_dir = directional_lights.data[i].direction;
- #define BIAS_FUNC(m_var, m_idx) \
- m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
- vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))) * directional_lights.data[i].shadow_normal_bias[m_idx]; \
- normal_bias -= light_dir * dot(light_dir, normal_bias); \
- m_var.xyz += normal_bias;
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 0)
- pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
- pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
- float range_pos = dot(directional_lights.data[i].direction, v.xyz);
- float range_begin = directional_lights.data[i].shadow_range_begin.x;
- float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
- vec2 tex_scale = directional_lights.data[i].uv_scale1 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
- }
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 1)
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
- pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
- float range_pos = dot(directional_lights.data[i].direction, v.xyz);
- float range_begin = directional_lights.data[i].shadow_range_begin.y;
- float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
- vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
- }
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 2)
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
- pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
- float range_pos = dot(directional_lights.data[i].direction, v.xyz);
- float range_begin = directional_lights.data[i].shadow_range_begin.z;
- float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
- vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
- }
- } else {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 3)
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
- pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
- float range_pos = dot(directional_lights.data[i].direction, v.xyz);
- float range_begin = directional_lights.data[i].shadow_range_begin.w;
- float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
- vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
- shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
- }
- }
- if (directional_lights.data[i].blend_splits) {
- float pssm_blend;
- float shadow2;
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 1)
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
- pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
- float range_pos = dot(directional_lights.data[i].direction, v.xyz);
- float range_begin = directional_lights.data[i].shadow_range_begin.y;
- float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
- vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
- shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
- }
- pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 2)
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
- pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
- float range_pos = dot(directional_lights.data[i].direction, v.xyz);
- float range_begin = directional_lights.data[i].shadow_range_begin.z;
- float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
- vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
- shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
- }
- pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 3)
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
- pssm_coord /= pssm_coord.w;
- if (directional_lights.data[i].softshadow_angle > 0) {
- float range_pos = dot(directional_lights.data[i].direction, v.xyz);
- float range_begin = directional_lights.data[i].shadow_range_begin.w;
- float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
- vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
- shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- } else {
- shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
- }
- pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
- } else {
- pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
- }
- pssm_blend = sqrt(pssm_blend);
- shadow = mix(shadow, shadow2, pssm_blend);
- }
- shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
- #undef BIAS_FUNC
- }
- #else
- // Soft shadow disabled version
- if (directional_lights.data[i].shadow_enabled) {
- float depth_z = -vertex.z;
- vec4 pssm_coord;
- vec3 light_dir = directional_lights.data[i].direction;
- vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp))));
- #define BIAS_FUNC(m_var, m_idx) \
- m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
- vec3 normal_bias = base_normal_bias * directional_lights.data[i].shadow_normal_bias[m_idx]; \
- normal_bias -= light_dir * dot(light_dir, normal_bias); \
- m_var.xyz += normal_bias;
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 0)
- pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 1)
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 2)
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
- } else {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 3)
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
- }
- pssm_coord /= pssm_coord.w;
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
- if (directional_lights.data[i].blend_splits) {
- float pssm_blend;
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 1)
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
- pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 2)
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
- pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 3)
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
- pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
- } else {
- pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
- }
- pssm_coord /= pssm_coord.w;
- float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
- shadow = mix(shadow, shadow2, pssm_blend);
- }
- shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
- #undef BIAS_FUNC
- }
- #endif
- if (i < 4) {
- shadow0 |= uint(clamp(shadow * 255.0, 0.0, 255.0)) << (i * 8);
- } else {
- shadow1 |= uint(clamp(shadow * 255.0, 0.0, 255.0)) << ((i - 4) * 8);
- }
- }
- #endif // SHADOWS_DISABLED
- for (uint i = 0; i < 8; i++) {
- if (i >= scene_data.directional_light_count) {
- break;
- }
- if (!bool(directional_lights.data[i].mask & draw_call.layer_mask)) {
- continue; //not masked
- }
- // We're not doing light transmittence
- float shadow = 1.0;
- #ifndef SHADOWS_DISABLED
- if (i < 4) {
- shadow = float(shadow0 >> (i * 8) & 0xFF) / 255.0;
- } else {
- shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
- }
- #endif
- blur_shadow(shadow);
- light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, albedo, alpha,
- #ifdef LIGHT_BACKLIGHT_USED
- backlight,
- #endif
- /* not supported here
- #ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_boost,
- transmittance_z,
- #endif
- */
- #ifdef LIGHT_RIM_USED
- rim, rim_tint,
- #endif
- #ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_roughness, normalize(normal_interp),
- #endif
- #ifdef LIGHT_ANISOTROPY_USED
- binormal, tangent, anisotropy,
- #endif
- #ifdef USE_SOFT_SHADOW
- directional_lights.data[i].size,
- #endif
- diffuse_light,
- specular_light);
- }
- } //directional light
- if (!sc_disable_omni_lights) { //omni lights
- uint light_indices = draw_call.omni_lights.x;
- for (uint i = 0; i < 8; i++) {
- uint light_index = light_indices & 0xFF;
- if (i == 4) {
- light_indices = draw_call.omni_lights.y;
- } else {
- light_indices = light_indices >> 8;
- }
- if (light_index == 0xFF) {
- break;
- }
- float shadow = light_process_omni_shadow(light_index, vertex, normal);
- shadow = blur_shadow(shadow);
- light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
- #ifdef LIGHT_BACKLIGHT_USED
- backlight,
- #endif
- /*
- #ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_boost,
- #endif
- */
- #ifdef LIGHT_RIM_USED
- rim,
- rim_tint,
- #endif
- #ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_roughness, normalize(normal_interp),
- #endif
- #ifdef LIGHT_ANISOTROPY_USED
- tangent,
- binormal, anisotropy,
- #endif
- diffuse_light, specular_light);
- }
- } //omni lights
- if (!sc_disable_spot_lights) { //spot lights
- uint light_indices = draw_call.spot_lights.x;
- for (uint i = 0; i < 8; i++) {
- uint light_index = light_indices & 0xFF;
- if (i == 4) {
- light_indices = draw_call.spot_lights.y;
- } else {
- light_indices = light_indices >> 8;
- }
- if (light_index == 0xFF) {
- break;
- }
- float shadow = light_process_spot_shadow(light_index, vertex, normal);
- shadow = blur_shadow(shadow);
- light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
- #ifdef LIGHT_BACKLIGHT_USED
- backlight,
- #endif
- /*
- #ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_boost,
- #endif
- */
- #ifdef LIGHT_RIM_USED
- rim,
- rim_tint,
- #endif
- #ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_roughness, normalize(normal_interp),
- #endif
- #ifdef LIGHT_ANISOTROPY_USED
- tangent,
- binormal, anisotropy,
- #endif
- diffuse_light, specular_light);
- }
- } //spot lights
- #ifdef USE_SHADOW_TO_OPACITY
- alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
- #if defined(ALPHA_SCISSOR_USED)
- if (alpha < alpha_scissor) {
- discard;
- }
- #endif // ALPHA_SCISSOR_USED
- #ifdef USE_OPAQUE_PREPASS
- if (alpha < scene_data.opaque_prepass_threshold) {
- discard;
- }
- #endif // USE_OPAQUE_PREPASS
- #endif // USE_SHADOW_TO_OPACITY
- #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
- #ifdef MODE_RENDER_DEPTH
- #ifdef MODE_RENDER_MATERIAL
- albedo_output_buffer.rgb = albedo;
- albedo_output_buffer.a = alpha;
- normal_output_buffer.rgb = normal * 0.5 + 0.5;
- normal_output_buffer.a = 0.0;
- depth_output_buffer.r = -vertex.z;
- orm_output_buffer.r = ao;
- orm_output_buffer.g = roughness;
- orm_output_buffer.b = metallic;
- orm_output_buffer.a = sss_strength;
- emission_output_buffer.rgb = emission;
- emission_output_buffer.a = 0.0;
- #endif // MODE_RENDER_MATERIAL
- #else // MODE_RENDER_DEPTH
- // multiply by albedo
- diffuse_light *= albedo; // ambient must be multiplied by albedo at the end
- // apply direct light AO
- ao = unpackUnorm4x8(orms).x;
- specular_light *= ao;
- diffuse_light *= ao;
- // apply metallic
- metallic = unpackUnorm4x8(orms).z;
- diffuse_light *= 1.0 - metallic;
- ambient_light *= 1.0 - metallic;
- //restore fog
- fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba));
- #ifdef MODE_MULTIPLE_RENDER_TARGETS
- #ifdef MODE_UNSHADED
- diffuse_buffer = vec4(albedo.rgb, 0.0);
- specular_buffer = vec4(0.0);
- #else // MODE_UNSHADED
- #ifdef SSS_MODE_SKIN
- sss_strength = -sss_strength;
- #endif // SSS_MODE_SKIN
- diffuse_buffer = vec4(emission + diffuse_light + ambient_light, sss_strength);
- specular_buffer = vec4(specular_light, metallic);
- #endif // MODE_UNSHADED
- diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a);
- specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a);
- #else //MODE_MULTIPLE_RENDER_TARGETS
- #ifdef MODE_UNSHADED
- frag_color = vec4(albedo, alpha);
- #else // MODE_UNSHADED
- frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha);
- #endif // MODE_UNSHADED
- // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
- frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
- // On mobile we use a UNORM buffer with 10bpp which results in a range from 0.0 - 1.0 resulting in HDR breaking
- // We divide by sc_luminance_multiplier to support a range from 0.0 - 2.0 both increasing precision on bright and darker images
- frag_color.rgb = frag_color.rgb / sc_luminance_multiplier;
- #endif //MODE_MULTIPLE_RENDER_TARGETS
- #endif //MODE_RENDER_DEPTH
- }
|