armory/Shaders/deferred_light/deferred_light.frag.glsl

493 lines
11 KiB
Plaintext
Raw Normal View History

2016-01-28 00:58:00 +01:00
#version 450
#include "compiled.inc"
#include "std/gbuffer.glsl"
#ifdef _Clusters
#include "std/clusters.glsl"
2017-08-17 14:37:04 +02:00
#endif
#ifdef _Irr
#include "std/shirr.glsl"
#endif
#ifdef _VoxelAOvar
#include "std/conetrace.glsl"
2016-10-17 17:39:40 +02:00
#endif
2017-05-23 15:01:56 +02:00
#ifdef _SSS
2017-12-13 14:21:42 +01:00
#include "std/sss.glsl"
2017-05-23 15:01:56 +02:00
#endif
2017-07-05 23:26:13 +02:00
#ifdef _SSRS
2017-12-13 14:21:42 +01:00
#include "std/ssrs.glsl"
2017-07-05 23:26:13 +02:00
#endif
2017-02-22 15:50:19 +01:00
2018-11-22 18:07:32 +01:00
uniform sampler2D gbufferD;
2016-03-20 18:44:11 +01:00
uniform sampler2D gbuffer0;
2016-06-07 09:38:49 +02:00
uniform sampler2D gbuffer1;
#ifdef _gbuffer2
uniform sampler2D gbuffer2;
#endif
#ifdef _VoxelAOvar
uniform sampler3D voxels;
#endif
#ifdef _VoxelGITemporal
uniform sampler3D voxelsLast;
uniform float voxelBlend;
#endif
#ifdef _VoxelGICam
uniform vec3 eyeSnap;
2018-05-19 19:29:14 +02:00
#endif
2016-01-03 19:41:00 +01:00
uniform float envmapStrength;
#ifdef _Irr
2020-05-10 19:43:02 +02:00
uniform vec4 shirr[7];
#endif
#ifdef _Brdf
uniform sampler2D senvmapBrdf;
2017-08-17 14:37:04 +02:00
#endif
#ifdef _Rad
uniform sampler2D senvmapRadiance;
uniform int envmapNumMipmaps;
#endif
#ifdef _EnvCol
uniform vec3 backgroundCol;
#endif
#ifdef _SSAO
uniform sampler2D ssaotex;
2018-11-07 13:11:38 +01:00
#endif
2016-06-07 09:38:49 +02:00
2017-11-17 16:15:35 +01:00
#ifdef _SSS
uniform vec2 lightPlane;
2017-11-17 16:15:35 +01:00
#endif
#ifdef _SSRS
//!uniform mat4 VP;
2016-08-09 23:51:40 +02:00
uniform mat4 invVP;
#endif
#ifdef _LightIES
//!uniform sampler2D texIES;
#endif
#ifdef _SMSizeUniform
2018-12-28 13:31:43 +01:00
//!uniform vec2 smSizeUniform;
#endif
2017-11-27 14:29:21 +01:00
#ifdef _LTC
2019-01-27 20:13:21 +01:00
//!uniform vec3 lightArea0;
//!uniform vec3 lightArea1;
//!uniform vec3 lightArea2;
//!uniform vec3 lightArea3;
//!uniform sampler2D sltcMat;
//!uniform sampler2D sltcMag;
2019-01-27 23:48:54 +01:00
#ifdef _ShadowMap
#ifdef _SinglePoint
//!uniform sampler2DShadow shadowMapSpot[1];
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
//!uniform mat4 LWVPSpot[1];
2019-01-27 23:48:54 +01:00
#endif
#ifdef _Clusters
//!uniform sampler2DShadow shadowMapSpot[4];
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
//!uniform mat4 LWVPSpotArray[4];
2019-01-27 23:48:54 +01:00
#endif
#endif
2016-11-08 15:14:56 +01:00
#endif
uniform vec2 cameraProj;
2016-03-20 18:44:11 +01:00
uniform vec3 eye;
uniform vec3 eyeLook;
#ifdef _Clusters
uniform vec4 lightsArray[maxLights * 3];
#ifdef _Spot
uniform vec4 lightsArraySpot[maxLights];
#endif
uniform sampler2D clustersData;
uniform vec2 cameraPlane;
2018-12-10 17:25:29 +01:00
#endif
#ifdef _ShadowMap
2018-12-15 19:03:11 +01:00
#ifdef _SinglePoint
#ifdef _Spot
//!uniform sampler2DShadow shadowMapSpot[1];
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
//!uniform mat4 LWVPSpot[1];
2018-12-15 19:03:11 +01:00
#else
//!uniform samplerCubeShadow shadowMapPoint[1];
2018-12-10 17:25:29 +01:00
//!uniform vec2 lightProj;
2018-12-15 19:03:11 +01:00
#endif
#endif
#ifdef _Clusters
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
#ifdef _ShadowMapAtlas
#ifdef _SingleAtlas
uniform sampler2DShadow shadowMapAtlas;
#endif
#endif
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlasPoint;
#endif
//!uniform vec4 pointLightDataArray[4];
#else
//!uniform samplerCubeShadow shadowMapPoint[4];
#endif
2018-12-15 19:03:11 +01:00
//!uniform vec2 lightProj;
#ifdef _Spot
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlasSpot;
#endif
#else
//!uniform sampler2DShadow shadowMapSpot[4];
#endif
//!uniform mat4 LWVPSpotArray[4];
#endif
2018-12-10 17:25:29 +01:00
#endif
2018-12-15 19:03:11 +01:00
#endif
2016-05-10 12:11:31 +02:00
#ifdef _Sun
uniform vec3 sunDir;
uniform vec3 sunCol;
#ifdef _ShadowMap
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasSun;
#endif
#else
2018-12-15 15:07:30 +01:00
uniform sampler2DShadow shadowMap;
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
#endif
uniform float shadowsBias;
#ifdef _CSM
//!uniform vec4 casData[shadowmapCascades * 4 + 4];
#else
uniform mat4 LWVP;
#endif
#endif // _ShadowMap
#endif
2018-12-10 17:25:29 +01:00
#ifdef _SinglePoint // Fast path for single light
uniform vec3 pointPos;
uniform vec3 pointCol;
2019-01-09 21:25:09 +01:00
#ifdef _ShadowMap
uniform float pointBias;
#endif
2018-12-10 17:25:29 +01:00
#ifdef _Spot
uniform vec3 spotDir;
uniform vec2 spotData;
#endif
#endif
#ifdef _LightClouds
uniform sampler2D texClouds;
uniform float time;
#endif
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
#include "std/light.glsl"
in vec2 texCoord;
in vec3 viewRay;
2016-10-12 17:52:27 +02:00
out vec4 fragColor;
2016-06-26 12:11:51 +02:00
2016-01-24 22:32:51 +01:00
void main() {
2019-01-23 18:09:53 +01:00
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, metallic/roughness, matid
2020-05-10 19:43:02 +02:00
2016-06-30 13:22:05 +02:00
vec3 n;
2016-08-07 23:12:14 +02:00
n.z = 1.0 - abs(g0.x) - abs(g0.y);
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
2016-06-30 13:22:05 +02:00
n = normalize(n);
2016-04-16 13:19:03 +02:00
2019-07-07 22:02:07 +02:00
float roughness = g0.b;
float metallic;
uint matid;
2019-07-14 16:45:34 +02:00
unpackFloatInt16(g0.a, metallic, matid);
2019-07-07 22:02:07 +02:00
2018-12-06 15:23:08 +01:00
vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ
vec2 occspec = unpackFloat2(g1.a);
2019-07-07 22:02:07 +02:00
vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor
vec3 f0 = surfaceF0(g1.rgb, metallic);
2017-03-17 18:34:03 +01:00
2018-12-06 15:23:08 +01:00
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
2018-12-05 17:47:45 +01:00
vec3 p = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
vec3 v = normalize(eye - p);
float dotNV = max(dot(n, v), 0.0);
#ifdef _gbuffer2
vec4 g2 = textureLod(gbuffer2, texCoord, 0.0);
#endif
2019-05-21 21:53:57 +02:00
#ifdef _MicroShadowing
occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel
#endif
#ifdef _Brdf
2019-07-07 22:02:07 +02:00
vec2 envBRDF = textureLod(senvmapBrdf, vec2(roughness, 1.0 - dotNV), 0.0).xy;
#endif
// Envmap
#ifdef _Irr
2020-05-10 19:43:02 +02:00
vec3 envl = shIrradiance(n, shirr);
#ifdef _gbuffer2
if (g2.b < 0.5) {
envl = envl;
} else {
envl = vec3(1.0);
}
#endif
#ifdef _EnvTex
envl /= PI;
#endif
#else
vec3 envl = vec3(1.0);
#endif
#ifdef _Rad
vec3 reflectionWorld = reflect(-v, n);
2019-07-07 22:02:07 +02:00
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
2017-02-22 15:50:19 +01:00
#endif
#ifdef _EnvLDR
envl.rgb = pow(envl.rgb, vec3(2.2));
#ifdef _Rad
prefilteredColor = pow(prefilteredColor, vec3(2.2));
#endif
#endif
envl.rgb *= albedo;
2020-05-10 19:43:02 +02:00
#ifdef _Rad // Indirect specular
envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5 * occspec.y;
#else
#ifdef _EnvCol
2019-07-07 22:02:07 +02:00
envl.rgb += backgroundCol * surfaceF0(g1.rgb, metallic); // f0
#endif
#endif
envl.rgb *= envmapStrength * occspec.x;
#ifdef _VoxelAOvar
2017-10-12 23:57:12 +02:00
#ifdef _VoxelGICam
vec3 voxpos = (p - eyeSnap) / voxelgiHalfExtents;
#else
vec3 voxpos = p / voxelgiHalfExtents;
#endif
2020-05-10 19:43:02 +02:00
2019-02-07 21:33:04 +01:00
#ifndef _VoxelAONoTrace
#ifdef _VoxelGITemporal
2018-12-07 13:48:40 +01:00
envl.rgb *= 1.0 - (traceAO(voxpos, n, voxels) * voxelBlend +
traceAO(voxpos, n, voxelsLast) * (1.0 - voxelBlend));
#else
envl.rgb *= 1.0 - traceAO(voxpos, n, voxels);
#endif
2019-02-07 21:33:04 +01:00
#endif
2020-05-10 19:43:02 +02:00
2017-08-13 20:28:06 +02:00
#endif
fragColor.rgb = envl;
2017-10-17 01:27:07 +02:00
#ifdef _SSAO
2018-12-06 20:36:56 +01:00
// #ifdef _RTGI
// fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).rgb;
// #else
2018-12-06 15:23:08 +01:00
fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r;
2018-12-06 20:36:56 +01:00
// #endif
2016-11-08 15:14:56 +01:00
#endif
2016-11-06 15:07:13 +01:00
2019-01-23 18:09:53 +01:00
#ifdef _Emission
if (matid == 1) {
2019-01-23 18:09:53 +01:00
fragColor.rgb += g1.rgb; // materialid
albedo = vec3(0.0);
}
#endif
// Show voxels
// vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99);
// vec3 direction = vec3(0.0, 0.0, -1.0);
// vec4 color = vec4(0.0f);
// for(uint step = 0; step < 400 && color.a < 0.99f; ++step) {
// vec3 point = origin + 0.005 * step * direction;
// color += (1.0f - color.a) * textureLod(voxels, point * 0.5 + 0.5, 0);
2020-05-10 19:43:02 +02:00
// }
// fragColor.rgb += color.rgb;
// Show SSAO
// fragColor.rgb = texture(ssaotex, texCoord).rrr;
#ifdef _Sun
vec3 sh = normalize(v + sunDir);
float sdotNH = dot(n, sh);
float sdotVH = dot(v, sh);
float sdotNL = dot(n, sunDir);
float svisibility = 1.0;
vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
2019-07-07 22:02:07 +02:00
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
2018-11-22 18:07:32 +01:00
#ifdef _ShadowMap
#ifdef _CSM
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
svisibility = shadowTestCascade(
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
shadowMapAtlasSun
#else
shadowMapAtlas
#endif
#else
shadowMap
#endif
, eye, p + n * shadowsBias * 10, shadowsBias
);
#else
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0);
if (lPos.w > 0.0) svisibility = shadowTest(
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
shadowMapAtlasSun
#else
shadowMapAtlas
#endif
#else
shadowMap
#endif
, lPos.xyz / lPos.w, shadowsBias
);
#endif
2018-11-22 18:07:32 +01:00
#endif
2019-01-27 19:12:00 +01:00
#ifdef _VoxelAOvar
#ifdef _VoxelShadow
2019-02-09 15:34:16 +01:00
svisibility *= 1.0 - traceShadow(voxels, voxpos, sunDir);
2019-01-27 19:12:00 +01:00
#endif
#endif
2018-11-23 18:03:27 +01:00
#ifdef _SSRS
// vec2 coords = getProjectedCoord(hitCoord);
// vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
// float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
2019-05-30 20:22:57 +02:00
svisibility *= traceShadowSS(sunDir, p, gbufferD, invVP, eye);
2018-11-23 18:03:27 +01:00
#endif
2019-01-10 12:35:13 +01:00
#ifdef _LightClouds
svisibility *= textureLod(texClouds, vec2(p.xy / 100.0 + time / 80.0), 0.0).r * dot(n, vec3(0,0,1));
#endif
2019-05-21 21:53:57 +02:00
#ifdef _MicroShadowing
svisibility *= sdotNL + 2.0 * occspec.x * occspec.x - 1.0;
#endif
fragColor.rgb += sdirect * svisibility * sunCol;
2016-08-29 09:56:34 +02:00
2019-01-24 12:47:51 +01:00
// #ifdef _Hair // Aniso
// if (matid == 2) {
2019-07-07 22:02:07 +02:00
// const float shinyParallel = roughness;
// const float shinyPerpendicular = 0.1;
// const vec3 v = vec3(0.99146, 0.11664, 0.05832);
// vec3 T = abs(dot(n, v)) > 0.99999 ? cross(n, vec3(0.0, 1.0, 0.0)) : cross(n, v);
2019-07-07 22:02:07 +02:00
// fragColor.rgb = orenNayarDiffuseBRDF(albedo, roughness, dotNV, dotNL, dotVH) + wardSpecular(n, h, dotNL, dotNV, dotNH, T, shinyParallel, shinyPerpendicular) * spec;
// }
2019-01-24 12:47:51 +01:00
// #endif
2019-01-24 12:47:51 +01:00
#ifdef _SSS
if (matid == 2) {
#ifdef _CSM
int casi, casindex;
mat4 LWVP = getCascadeMat(distance(eye, p), casi, casindex);
#endif
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
fragColor.rgb += fragColor.rgb * SSSSTransmittance(
LWVP, p, n, sunDir, lightPlane.y,
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
shadowMapAtlasSun
#else
shadowMapAtlas
#endif
#else
shadowMap
#endif
);
2016-05-01 00:56:40 +02:00
}
2019-01-24 12:47:51 +01:00
#endif
#endif // _Sun
2016-03-20 18:44:11 +01:00
2018-12-10 17:25:29 +01:00
#ifdef _SinglePoint
2019-01-27 19:12:00 +01:00
2018-12-10 17:25:29 +01:00
fragColor.rgb += sampleLight(
2019-07-07 22:02:07 +02:00
p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0
2018-12-10 17:25:29 +01:00
#ifdef _ShadowMap
, 0, pointBias, true
2018-12-10 17:25:29 +01:00
#endif
#ifdef _Spot
, true, spotData.x, spotData.y, spotDir
#endif
2019-01-27 19:12:00 +01:00
#ifdef _VoxelAOvar
#ifdef _VoxelShadow
, voxels, voxpos
#endif
#endif
2019-05-21 21:53:57 +02:00
#ifdef _MicroShadowing
, occspec.x
#endif
2019-05-30 20:22:57 +02:00
#ifdef _SSRS
, gbufferD, invVP, eye
#endif
2018-12-10 17:25:29 +01:00
);
2020-05-10 19:43:02 +02:00
2019-01-24 12:47:51 +01:00
#ifdef _Spot
#ifdef _SSS
if (matid == 2) fragColor.rgb += fragColor.rgb * SSSSTransmittance(LWVPSpot0, p, n, normalize(pointPos - p), lightPlane.y, shadowMapSpot[0]);
2019-01-24 12:47:51 +01:00
#endif
2020-05-10 19:43:02 +02:00
#endif
2019-01-27 19:12:00 +01:00
2018-12-10 17:25:29 +01:00
#endif
#ifdef _Clusters
2018-12-09 19:27:11 +01:00
float viewz = linearize(depth * 0.5 + 0.5, cameraProj);
int clusterI = getClusterI(texCoord, viewz, cameraPlane);
int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);
2018-11-29 23:43:33 +01:00
#ifdef HLSL
2018-12-09 19:27:11 +01:00
viewz += textureLod(clustersData, vec2(0.0), 0.0).r * 1e-9; // TODO: krafix bug, needs to generate sampler
2018-11-29 23:43:33 +01:00
#endif
#ifdef _Spot
int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255);
int numPoints = numLights - numSpots;
#endif
2018-11-28 10:26:48 +01:00
for (int i = 0; i < min(numLights, maxLightsCluster); i++) {
int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255);
2018-12-10 17:25:29 +01:00
fragColor.rgb += sampleLight(
p,
n,
v,
dotNV,
lightsArray[li * 3].xyz, // lp
lightsArray[li * 3 + 1].xyz, // lightCol
2018-12-10 17:25:29 +01:00
albedo,
2019-07-07 22:02:07 +02:00
roughness,
2018-12-10 17:25:29 +01:00
occspec.y,
f0
#ifdef _ShadowMap
// light index, shadow bias, cast_shadows
, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0
#endif
2018-12-10 17:25:29 +01:00
#ifdef _Spot
, lightsArray[li * 3 + 2].y != 0.0
, lightsArray[li * 3 + 2].y // cutoff
2018-12-10 17:25:29 +01:00
, lightsArraySpot[li].w // cutoff - exponent
2018-12-10 18:18:32 +01:00
, lightsArraySpot[li].xyz // spotDir
2018-12-10 17:25:29 +01:00
#endif
2019-05-21 21:53:57 +02:00
#ifdef _MicroShadowing
, occspec.x
#endif
2019-05-30 20:22:57 +02:00
#ifdef _SSRS
, gbufferD, invVP, eye
#endif
2018-12-10 17:25:29 +01:00
);
}
2018-12-10 17:25:29 +01:00
#endif // _Clusters
2019-04-16 13:30:35 +02:00
fragColor.a = 1.0; // Mark as opaque
2016-01-03 19:41:00 +01:00
}