123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911 |
- #[vertex]
- #version 450
- #VERSION_DEFINES
- #include "scene_forward_clustered_inc.glsl"
- /* 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
- #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) out vec3 vertex_interp;
- #ifdef NORMAL_USED
- layout(location = 1) out vec3 normal_interp;
- #endif
- #if defined(COLOR_USED)
- layout(location = 2) out vec4 color_interp;
- #endif
- #ifdef UV_USED
- layout(location = 3) out vec2 uv_interp;
- #endif
- #if defined(UV2_USED) || defined(USE_LIGHTMAP)
- layout(location = 4) out vec2 uv2_interp;
- #endif
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- layout(location = 5) out vec3 tangent_interp;
- layout(location = 6) 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 float dp_clip;
- #endif
- layout(location = 9) out flat uint instance_index_interp;
- invariant gl_Position;
- #GLOBALS
- void main() {
- vec4 instance_custom = vec4(0.0);
- #if defined(COLOR_USED)
- color_interp = color_attrib;
- #endif
- uint instance_index = draw_call.instance_index;
- bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH);
- if (!is_multimesh) {
- instance_index += gl_InstanceIndex;
- }
- instance_index_interp = instance_index;
- mat4 world_matrix = instances.data[instance_index].transform;
- mat3 world_normal_matrix;
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
- world_normal_matrix = transpose(inverse(mat3(world_matrix)));
- } else {
- world_normal_matrix = mat3(world_matrix);
- }
- if (is_multimesh) {
- //multimesh, instances are for it
- mat4 matrix;
- #ifdef USE_PARTICLE_TRAILS
- uint trail_size = (instances.data[instance_index].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(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
- stride += 2;
- } else {
- stride += 3;
- }
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
- stride += 1;
- }
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
- stride += 1;
- }
- }
- uint offset = stride * gl_InstanceIndex;
- if (bool(instances.data[instance_index].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(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
- #ifdef COLOR_USED
- color_interp *= transforms.data[offset];
- #endif
- offset += 1;
- }
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
- instance_custom = transforms.data[offset];
- }
- #endif
- //transpose
- matrix = transpose(matrix);
- world_matrix = world_matrix * matrix;
- world_normal_matrix = world_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
- mat4 projection_matrix = scene_data.projection_matrix;
- //using world coordinates
- #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
- vertex = (world_matrix * vec4(vertex, 1.0)).xyz;
- normal = world_normal_matrix * normal;
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- tangent = world_normal_matrix * tangent;
- binormal = world_normal_matrix * binormal;
- #endif
- #endif
- float roughness = 1.0;
- mat4 modelview = scene_data.inv_camera_matrix * world_matrix;
- mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * world_normal_matrix;
- {
- #CODE : VERTEX
- }
- // 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.inv_camera_matrix * vec4(vertex, 1.0)).xyz;
- normal = mat3(scene_data.inverse_normal_matrix) * normal;
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- binormal = mat3(scene_data.camera_inverse_binormal_matrix) * binormal;
- tangent = mat3(scene_data.camera_inverse_tangent_matrix) * tangent;
- #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
- #ifdef MODE_RENDER_DEPTH
- if (scene_data.pancake_shadows) {
- if (gl_Position.z <= 0.00001) {
- gl_Position.z = 0.00001;
- }
- }
- #endif
- #ifdef MODE_RENDER_MATERIAL
- if (scene_data.material_uv2_mode) {
- vec2 uv_offset = unpackHalf2x16(draw_call.uv_offset);
- gl_Position.xy = (uv2_attrib.xy + uv_offset) * 2.0 - 1.0;
- gl_Position.z = 0.00001;
- gl_Position.w = 1.0;
- }
- #endif
- }
- #[fragment]
- #version 450
- #VERSION_DEFINES
- /* Specialization Constants (Toggles) */
- layout(constant_id = 0) const bool sc_use_forward_gi = false;
- layout(constant_id = 1) const bool sc_use_light_projector = false;
- layout(constant_id = 2) const bool sc_use_light_soft_shadows = false;
- layout(constant_id = 3) const bool sc_use_directional_soft_shadows = false;
- /* Specialization Constants (Values) */
- layout(constant_id = 6) const uint sc_soft_shadow_samples = 4;
- layout(constant_id = 7) const uint sc_penumbra_shadow_samples = 4;
- layout(constant_id = 8) const uint sc_directional_soft_shadow_samples = 4;
- layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4;
- layout(constant_id = 10) const bool sc_decal_use_mipmaps = true;
- layout(constant_id = 11) const bool sc_projector_use_mipmaps = true;
- // not used in clustered renderer but we share some code with the mobile renderer that requires this.
- const float sc_luminance_multiplier = 1.0;
- #include "scene_forward_clustered_inc.glsl"
- /* Varyings */
- layout(location = 0) in vec3 vertex_interp;
- #ifdef NORMAL_USED
- layout(location = 1) in vec3 normal_interp;
- #endif
- #if defined(COLOR_USED)
- layout(location = 2) in vec4 color_interp;
- #endif
- #ifdef UV_USED
- layout(location = 3) in vec2 uv_interp;
- #endif
- #if defined(UV2_USED) || defined(USE_LIGHTMAP)
- layout(location = 4) in vec2 uv2_interp;
- #endif
- #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- layout(location = 5) in vec3 tangent_interp;
- layout(location = 6) in vec3 binormal_interp;
- #endif
- #ifdef MODE_DUAL_PARABOLOID
- layout(location = 8) in float dp_clip;
- #endif
- layout(location = 9) in flat uint instance_index_interp;
- //defines to keep compatibility with vertex
- #define world_matrix instances.data[instance_index].transform
- #define projection_matrix scene_data.projection_matrix
- #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
- #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
- #ifdef MODE_RENDER_NORMAL_ROUGHNESS
- layout(location = 0) out vec4 normal_roughness_output_buffer;
- #ifdef MODE_RENDER_VOXEL_GI
- layout(location = 1) out uvec2 voxel_gi_buffer;
- #endif
- #endif //MODE_RENDER_NORMAL
- #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 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)
- /* Make a default specular mode SPECULAR_SCHLICK_GGX. */
- #if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN) && !defined(SPECULAR_PHONG) && !defined(SPECULAR_TOON)
- #define SPECULAR_SCHLICK_GGX
- #endif
- #include "scene_forward_lights_inc.glsl"
- #include "scene_forward_gi_inc.glsl"
- #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
- #ifndef MODE_RENDER_DEPTH
- vec4 volumetric_fog_process(vec2 screen_uv, float z) {
- vec3 fog_pos = vec3(screen_uv, z * scene_data.volumetric_fog_inv_length);
- if (fog_pos.z < 0.0) {
- return vec4(0.0);
- } else if (fog_pos.z < 1.0) {
- fog_pos.z = pow(fog_pos.z, scene_data.volumetric_fog_detail_spread);
- }
- return texture(sampler3D(volumetric_fog_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), fog_pos);
- }
- 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.camera_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);
- }
- void cluster_get_item_range(uint p_offset, out uint item_min, out uint item_max, out uint item_from, out uint item_to) {
- uint item_min_max = cluster_buffer.data[p_offset];
- item_min = item_min_max & 0xFFFF;
- item_max = item_min_max >> 16;
- ;
- item_from = item_min >> 5;
- item_to = (item_max == 0) ? 0 : ((item_max - 1) >> 5) + 1; //side effect of how it is stored, as item_max 0 means no elements
- }
- uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) {
- int local_min = clamp(int(z_min) - int(i) * 32, 0, 31);
- int mask_width = min(int(z_max) - int(z_min), 32 - local_min);
- return bitfieldInsert(uint(0), uint(0xFFFFFFFF), local_min, mask_width);
- }
- #endif //!MODE_RENDER DEPTH
- void main() {
- #ifdef MODE_DUAL_PARABOLOID
- if (dp_clip > 0.0)
- discard;
- #endif
- uint instance_index = instance_index_interp;
- //lay out everything, whathever 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, 0.0, 0.0, 1.0);
- float transmittance_depth = 0.0;
- float transmittance_boost = 0.0;
- float metallic = 0.0;
- float specular = 0.5;
- vec3 emission = vec3(0.0);
- float roughness = 1.0;
- float rim = 0.0;
- float rim_tint = 0.0;
- float clearcoat = 0.0;
- float clearcoat_gloss = 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 = float(instances.data[instance_index].flags >> INSTANCE_FLAGS_FADE_SHIFT) / float(255.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
- transmittance_color.a *= sss_strength;
- #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 < 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 (scene_data.fog_enabled) {
- fog = fog_process(vertex);
- }
- if (scene_data.volumetric_fog_enabled) {
- vec4 volumetric_fog = volumetric_fog_process(screen_uv, -vertex.z);
- if (scene_data.fog_enabled) {
- //must use the full blending equation here to blend fogs
- vec4 res;
- float sa = 1.0 - volumetric_fog.a;
- res.a = fog.a * sa + volumetric_fog.a;
- if (res.a == 0.0) {
- res.rgb = vec3(0.0);
- } else {
- res.rgb = (fog.rgb * fog.a * sa + volumetric_fog.rgb * volumetric_fog.a) / res.a;
- }
- fog = res;
- } else {
- fog = volumetric_fog;
- }
- }
- #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
- uvec2 cluster_pos = uvec2(gl_FragCoord.xy) >> scene_data.cluster_shift;
- uint cluster_offset = (scene_data.cluster_width * cluster_pos.y + cluster_pos.x) * (scene_data.max_cluster_element_count_div_32 + 32);
- uint cluster_z = uint(clamp((-vertex.z / scene_data.z_far) * 32.0, 0.0, 31.0));
- //used for interpolating anything cluster related
- vec3 vertex_ddx = dFdx(vertex);
- vec3 vertex_ddy = dFdy(vertex);
- { // process decals
- uint cluster_decal_offset = cluster_offset + scene_data.cluster_type_size * 2;
- uint item_min;
- uint item_max;
- uint item_from;
- uint item_to;
- cluster_get_item_range(cluster_decal_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
- #ifdef USE_SUBGROUPS
- item_from = subgroupBroadcastFirst(subgroupMin(item_from));
- item_to = subgroupBroadcastFirst(subgroupMax(item_to));
- #endif
- for (uint i = item_from; i < item_to; i++) {
- uint mask = cluster_buffer.data[cluster_decal_offset + i];
- mask &= cluster_get_range_clip_mask(i, item_min, item_max);
- #ifdef USE_SUBGROUPS
- uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
- #else
- uint merged_mask = mask;
- #endif
- while (merged_mask != 0) {
- uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
- #ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
- continue;
- }
- #endif
- uint decal_index = 32 * i + bit;
- if (!bool(decals.data[decal_index].mask & instances.data[instance_index].layer_mask)) {
- continue; //not masked
- }
- 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;
- }
- }
- }
- }
- }
- //pack albedo until needed again, saves 2 VGPRs in the meantime
- #endif //not 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
- //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) {
- vec3 ref_vec = reflect(-view, normal);
- 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
- 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
- #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(ambient_light, custom_irradiance.rgb, custom_irradiance.a);
- #endif
- #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
- //radiance
- /// GI ///
- #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
- #ifdef USE_LIGHTMAP
- //lightmap
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
- uint index = instances.data[instance_index].gi_offset;
- vec3 wnormal = mat3(scene_data.camera_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(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
- bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
- uint ofs = instances.data[instance_index].gi_offset & 0xFFFF;
- vec3 uvw;
- uvw.xy = uv2 * instances.data[instance_index].lightmap_uv_scale.zw + instances.data[instance_index].lightmap_uv_scale.xy;
- uvw.z = float((instances.data[instance_index].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 = instances.data[instance_index].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;
- }
- }
- #else
- if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
- //make vertex orientation the world one, but still align to camera
- vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex;
- vec3 cam_normal = mat3(scene_data.camera_matrix) * normal;
- vec3 cam_reflection = mat3(scene_data.camera_matrix) * reflect(-view, normal);
- //apply y-mult
- cam_pos.y *= sdfgi.y_mult;
- cam_normal.y *= sdfgi.y_mult;
- cam_normal = normalize(cam_normal);
- cam_reflection.y *= sdfgi.y_mult;
- cam_normal = normalize(cam_normal);
- cam_reflection = normalize(cam_reflection);
- vec4 light_accum = vec4(0.0);
- float weight_accum = 0.0;
- vec4 light_blend_accum = vec4(0.0);
- float weight_blend_accum = 0.0;
- float blend = -1.0;
- // helper constants, compute once
- uint cascade = 0xFFFFFFFF;
- vec3 cascade_pos;
- vec3 cascade_normal;
- for (uint i = 0; i < sdfgi.max_cascades; i++) {
- cascade_pos = (cam_pos - sdfgi.cascades[i].position) * sdfgi.cascades[i].to_probe;
- if (any(lessThan(cascade_pos, vec3(0.0))) || any(greaterThanEqual(cascade_pos, sdfgi.cascade_probe_size))) {
- continue; //skip cascade
- }
- cascade = i;
- break;
- }
- if (cascade < SDFGI_MAX_CASCADES) {
- bool use_specular = true;
- float blend;
- vec3 diffuse, specular;
- sdfgi_process(cascade, cascade_pos, cam_pos, cam_normal, cam_reflection, use_specular, roughness, diffuse, specular, blend);
- if (blend > 0.0) {
- //blend
- if (cascade == sdfgi.max_cascades - 1) {
- diffuse = mix(diffuse, ambient_light, blend);
- if (use_specular) {
- specular = mix(specular, specular_light, blend);
- }
- } else {
- vec3 diffuse2, specular2;
- float blend2;
- cascade_pos = (cam_pos - sdfgi.cascades[cascade + 1].position) * sdfgi.cascades[cascade + 1].to_probe;
- sdfgi_process(cascade + 1, cascade_pos, cam_pos, cam_normal, cam_reflection, use_specular, roughness, diffuse2, specular2, blend2);
- diffuse = mix(diffuse, diffuse2, blend);
- if (use_specular) {
- specular = mix(specular, specular2, blend);
- }
- }
- }
- ambient_light = diffuse;
- if (use_specular) {
- specular_light = specular;
- }
- }
- }
- if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
- uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
- vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
- //find arbitrary tangent and bitangent, then build a matrix
- vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
- vec3 tangent = normalize(cross(v0, normal));
- vec3 bitangent = normalize(cross(tangent, normal));
- mat3 normal_mat = mat3(tangent, bitangent, normal);
- vec4 amb_accum = vec4(0.0);
- vec4 spec_accum = vec4(0.0);
- voxel_gi_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
- uint index2 = instances.data[instance_index].gi_offset >> 16;
- if (index2 != 0xFFFF) {
- voxel_gi_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
- }
- if (amb_accum.a > 0.0) {
- amb_accum.rgb /= amb_accum.a;
- }
- if (spec_accum.a > 0.0) {
- spec_accum.rgb /= spec_accum.a;
- }
- specular_light = spec_accum.rgb;
- ambient_light = amb_accum.rgb;
- }
- if (!sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
- vec2 coord;
- if (scene_data.gi_upscale_for_msaa) {
- vec2 base_coord = screen_uv;
- vec2 closest_coord = base_coord;
- float closest_ang = dot(normal, textureLod(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord, 0.0).xyz * 2.0 - 1.0);
- for (int i = 0; i < 4; i++) {
- const vec2 neighbours[4] = vec2[](vec2(-1, 0), vec2(1, 0), vec2(0, -1), vec2(0, 1));
- vec2 neighbour_coord = base_coord + neighbours[i] * scene_data.screen_pixel_size;
- float neighbour_ang = dot(normal, textureLod(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), neighbour_coord, 0.0).xyz * 2.0 - 1.0);
- if (neighbour_ang > closest_ang) {
- closest_ang = neighbour_ang;
- closest_coord = neighbour_coord;
- }
- }
- coord = closest_coord;
- } else {
- coord = screen_uv;
- }
- vec4 buffer_ambient = textureLod(sampler2D(ambient_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0.0);
- vec4 buffer_reflection = textureLod(sampler2D(reflection_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0.0);
- ambient_light = mix(ambient_light, buffer_ambient.rgb, buffer_ambient.a);
- specular_light = mix(specular_light, buffer_reflection.rgb, buffer_reflection.a);
- }
- #endif // !USE_LIGHTMAP
- if (scene_data.ssao_enabled) {
- float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r;
- ao = min(ao, ssao);
- ao_light_affect = mix(ao_light_affect, max(ao_light_affect, scene_data.ssao_light_affect), scene_data.ssao_ao_affect);
- }
- { // process reflections
- 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 cluster_reflection_offset = cluster_offset + scene_data.cluster_type_size * 3;
- uint item_min;
- uint item_max;
- uint item_from;
- uint item_to;
- cluster_get_item_range(cluster_reflection_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
- #ifdef USE_SUBGROUPS
- item_from = subgroupBroadcastFirst(subgroupMin(item_from));
- item_to = subgroupBroadcastFirst(subgroupMax(item_to));
- #endif
- for (uint i = item_from; i < item_to; i++) {
- uint mask = cluster_buffer.data[cluster_reflection_offset + i];
- mask &= cluster_get_range_clip_mask(i, item_min, item_max);
- #ifdef USE_SUBGROUPS
- uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
- #else
- uint merged_mask = mask;
- #endif
- while (merged_mask != 0) {
- uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
- #ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
- continue;
- }
- #endif
- uint reflection_index = 32 * i + bit;
- if (!bool(reflections.data[reflection_index].mask & instances.data[instance_index].layer_mask)) {
- continue; //not masked
- }
- reflection_process(reflection_index, vertex, 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
- }
- //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 //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)
- { // Directional light.
- // Do shadow and lighting in two passes to reduce register pressure.
- #ifndef SHADOWS_DISABLED
- 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 & instances.data[instance_index].layer_mask)) {
- continue; //not masked
- }
- if (directional_lights.data[i].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) {
- continue; // Statically baked light and object uses lightmap, skip
- }
- float shadow = 1.0;
- if (directional_lights.data[i].shadow_enabled) {
- float depth_z = -vertex.z;
- 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;
- //version with soft shadows, more expensive
- if (sc_use_directional_soft_shadows && directional_lights.data[i].softshadow_angle > 0) {
- uint blend_count = 0;
- const uint blend_max = directional_lights.data[i].blend_splits ? 2 : 1;
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 0)
- vec4 pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
- pssm_coord /= pssm_coord.w;
- 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);
- blend_count++;
- }
- if (blend_count < blend_max && depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 1)
- vec4 pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
- pssm_coord /= pssm_coord.w;
- 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;
- float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- if (blend_count == 0) {
- shadow = s;
- } else {
- //blend
- float blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
- shadow = mix(shadow, s, blend);
- }
- blend_count++;
- }
- if (blend_count < blend_max && depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 2)
- vec4 pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
- pssm_coord /= pssm_coord.w;
- 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;
- float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- if (blend_count == 0) {
- shadow = s;
- } else {
- //blend
- float blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
- shadow = mix(shadow, s, blend);
- }
- blend_count++;
- }
- if (blend_count < blend_max) {
- vec4 v = vec4(vertex, 1.0);
- BIAS_FUNC(v, 3)
- vec4 pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
- pssm_coord /= pssm_coord.w;
- 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;
- float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- if (blend_count == 0) {
- shadow = s;
- } else {
- //blend
- float blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
- shadow = mix(shadow, s, blend);
- }
- }
- } else { //no soft shadows
- vec4 pssm_coord;
- 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
- } // shadows
- 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 & instances.data[instance_index].layer_mask)) {
- continue; //not masked
- }
- #ifdef LIGHT_TRANSMITTANCE_USED
- float transmittance_z = transmittance_depth;
- if (directional_lights.data[i].shadow_enabled) {
- float depth_z = -vertex.z;
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.x, 1.0);
- vec4 trans_coord = directional_lights.data[i].shadow_matrix1 * trans_vertex;
- trans_coord /= trans_coord.w;
- float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_z_range.x;
- float z = trans_coord.z * directional_lights.data[i].shadow_z_range.x;
- transmittance_z = z - shadow_z;
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.y, 1.0);
- vec4 trans_coord = directional_lights.data[i].shadow_matrix2 * trans_vertex;
- trans_coord /= trans_coord.w;
- float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_z_range.y;
- float z = trans_coord.z * directional_lights.data[i].shadow_z_range.y;
- transmittance_z = z - shadow_z;
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.z, 1.0);
- vec4 trans_coord = directional_lights.data[i].shadow_matrix3 * trans_vertex;
- trans_coord /= trans_coord.w;
- float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_z_range.z;
- float z = trans_coord.z * directional_lights.data[i].shadow_z_range.z;
- transmittance_z = z - shadow_z;
- } else {
- vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.w, 1.0);
- vec4 trans_coord = directional_lights.data[i].shadow_matrix4 * trans_vertex;
- trans_coord /= trans_coord.w;
- float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_z_range.w;
- float z = trans_coord.z * directional_lights.data[i].shadow_z_range.w;
- transmittance_z = z - shadow_z;
- }
- }
- #endif
- 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);
- float size_A = sc_use_light_soft_shadows ? directional_lights.data[i].size : 0.0;
- light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
- #ifdef LIGHT_BACKLIGHT_USED
- backlight,
- #endif
- #ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_boost,
- transmittance_z,
- #endif
- #ifdef LIGHT_RIM_USED
- rim, rim_tint, albedo,
- #endif
- #ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_gloss,
- #endif
- #ifdef LIGHT_ANISOTROPY_USED
- binormal, tangent, anisotropy,
- #endif
- #ifdef USE_SHADOW_TO_OPACITY
- alpha,
- #endif
- diffuse_light,
- specular_light);
- }
- }
- { //omni lights
- uint cluster_omni_offset = cluster_offset;
- uint item_min;
- uint item_max;
- uint item_from;
- uint item_to;
- cluster_get_item_range(cluster_omni_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
- #ifdef USE_SUBGROUPS
- item_from = subgroupBroadcastFirst(subgroupMin(item_from));
- item_to = subgroupBroadcastFirst(subgroupMax(item_to));
- #endif
- for (uint i = item_from; i < item_to; i++) {
- uint mask = cluster_buffer.data[cluster_omni_offset + i];
- mask &= cluster_get_range_clip_mask(i, item_min, item_max);
- #ifdef USE_SUBGROUPS
- uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
- #else
- uint merged_mask = mask;
- #endif
- while (merged_mask != 0) {
- uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
- #ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
- continue;
- }
- #endif
- uint light_index = 32 * i + bit;
- if (!bool(omni_lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
- continue; //not masked
- }
- if (omni_lights.data[light_index].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) {
- continue; // Statically baked light and object uses lightmap, skip
- }
- 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,
- #ifdef LIGHT_BACKLIGHT_USED
- backlight,
- #endif
- #ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_boost,
- #endif
- #ifdef LIGHT_RIM_USED
- rim,
- rim_tint,
- albedo,
- #endif
- #ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_gloss,
- #endif
- #ifdef LIGHT_ANISOTROPY_USED
- tangent, binormal, anisotropy,
- #endif
- #ifdef USE_SHADOW_TO_OPACITY
- alpha,
- #endif
- diffuse_light, specular_light);
- }
- }
- }
- { //spot lights
- uint cluster_spot_offset = cluster_offset + scene_data.cluster_type_size;
- uint item_min;
- uint item_max;
- uint item_from;
- uint item_to;
- cluster_get_item_range(cluster_spot_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
- #ifdef USE_SUBGROUPS
- item_from = subgroupBroadcastFirst(subgroupMin(item_from));
- item_to = subgroupBroadcastFirst(subgroupMax(item_to));
- #endif
- for (uint i = item_from; i < item_to; i++) {
- uint mask = cluster_buffer.data[cluster_spot_offset + i];
- mask &= cluster_get_range_clip_mask(i, item_min, item_max);
- #ifdef USE_SUBGROUPS
- uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
- #else
- uint merged_mask = mask;
- #endif
- while (merged_mask != 0) {
- uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
- #ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
- continue;
- }
- #endif
- uint light_index = 32 * i + bit;
- if (!bool(spot_lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
- continue; //not masked
- }
- if (spot_lights.data[light_index].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) {
- continue; // Statically baked light and object uses lightmap, skip
- }
- 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,
- #ifdef LIGHT_BACKLIGHT_USED
- backlight,
- #endif
- #ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_boost,
- #endif
- #ifdef LIGHT_RIM_USED
- rim,
- rim_tint,
- albedo,
- #endif
- #ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_gloss,
- #endif
- #ifdef LIGHT_ANISOTROPY_USED
- tangent, binormal, anisotropy,
- #endif
- #ifdef USE_SHADOW_TO_OPACITY
- alpha,
- #endif
- diffuse_light, specular_light);
- }
- }
- }
- #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 < 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_SDF
- {
- vec3 local_pos = (scene_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz;
- ivec3 grid_pos = scene_data.sdf_offset + ivec3(local_pos * vec3(scene_data.sdf_size));
- uint albedo16 = 0x1; //solid flag
- albedo16 |= clamp(uint(albedo.r * 31.0), 0, 31) << 11;
- albedo16 |= clamp(uint(albedo.g * 31.0), 0, 31) << 6;
- albedo16 |= clamp(uint(albedo.b * 31.0), 0, 31) << 1;
- imageStore(albedo_volume_grid, grid_pos, uvec4(albedo16));
- uint facing_bits = 0;
- const vec3 aniso_dir[6] = vec3[](
- vec3(1, 0, 0),
- vec3(0, 1, 0),
- vec3(0, 0, 1),
- vec3(-1, 0, 0),
- vec3(0, -1, 0),
- vec3(0, 0, -1));
- vec3 cam_normal = mat3(scene_data.camera_matrix) * normalize(normal_interp);
- float closest_dist = -1e20;
- for (uint i = 0; i < 6; i++) {
- float d = dot(cam_normal, aniso_dir[i]);
- if (d > closest_dist) {
- closest_dist = d;
- facing_bits = (1 << i);
- }
- }
- imageAtomicOr(geom_facing_grid, grid_pos, facing_bits); //store facing bits
- if (length(emission) > 0.001) {
- float lumas[6];
- vec3 light_total = vec3(0);
- for (int i = 0; i < 6; i++) {
- float strength = max(0.0, dot(cam_normal, aniso_dir[i]));
- vec3 light = emission * strength;
- light_total += light;
- lumas[i] = max(light.r, max(light.g, light.b));
- }
- float luma_total = max(light_total.r, max(light_total.g, light_total.b));
- uint light_aniso = 0;
- for (int i = 0; i < 6; i++) {
- light_aniso |= min(31, uint((lumas[i] / luma_total) * 31.0)) << (i * 5);
- }
- //compress to RGBE9995 to save space
- const float pow2to9 = 512.0f;
- const float B = 15.0f;
- const float N = 9.0f;
- const float LN2 = 0.6931471805599453094172321215;
- float cRed = clamp(light_total.r, 0.0, 65408.0);
- float cGreen = clamp(light_total.g, 0.0, 65408.0);
- float cBlue = clamp(light_total.b, 0.0, 65408.0);
- float cMax = max(cRed, max(cGreen, cBlue));
- float expp = max(-B - 1.0f, floor(log(cMax) / LN2)) + 1.0f + B;
- float sMax = floor((cMax / pow(2.0f, expp - B - N)) + 0.5f);
- float exps = expp + 1.0f;
- if (0.0 <= sMax && sMax < pow2to9) {
- exps = expp;
- }
- float sRed = floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
- float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
- float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
- //store as 8985 to have 2 extra neighbour bits
- uint light_rgbe = ((uint(sRed) & 0x1FF) >> 1) | ((uint(sGreen) & 0x1FF) << 8) | (((uint(sBlue) & 0x1FF) >> 1) << 17) | ((uint(exps) & 0x1F) << 25);
- imageStore(emission_grid, grid_pos, uvec4(light_rgbe));
- imageStore(emission_aniso_grid, grid_pos, uvec4(light_aniso));
- }
- }
- #endif
- #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
- #ifdef MODE_RENDER_NORMAL_ROUGHNESS
- normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness);
- #ifdef MODE_RENDER_VOXEL_GI
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
- uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
- uint index2 = instances.data[instance_index].gi_offset >> 16;
- voxel_gi_buffer.x = index1 & 0xFF;
- voxel_gi_buffer.y = index2 & 0xFF;
- } else {
- voxel_gi_buffer.x = 0xFF;
- voxel_gi_buffer.y = 0xFF;
- }
- #endif
- #endif //MODE_RENDER_NORMAL_ROUGHNESS
- //nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
- #else
- // 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
- #ifdef SSS_MODE_SKIN
- sss_strength = -sss_strength;
- #endif
- diffuse_buffer = vec4(emission + diffuse_light + ambient_light, sss_strength);
- specular_buffer = vec4(specular_light, metallic);
- #endif
- 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
- frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha);
- //frag_color = vec4(1.0);
- #endif //USE_NO_SHADING
- // 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);
- #endif //MODE_MULTIPLE_RENDER_TARGETS
- #endif //MODE_RENDER_DEPTH
- }
|