add directional light component and skylight component, add PCSS and hard shadow
This commit is contained in:
@ -1,155 +0,0 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetPath: assets/env/pink_sunrise_4k.hdr
|
||||
Light:
|
||||
Direction: [-0.787, -0.73299998, 1]
|
||||
Radiance: [1, 1, 1]
|
||||
Multiplier: 0.514999986
|
||||
Entities:
|
||||
- Entity: 12498244675852797835
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-12.0348625, 6.59647179, 9.60061925e-07]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [3.00000024, 0.300000012, 1]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 0
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [1.5, 0.150000006]
|
||||
Density: 1
|
||||
Friction: 1
|
||||
- Entity: 5178862374589434728
|
||||
TagComponent:
|
||||
Tag: Camera
|
||||
TransformComponent:
|
||||
Position: [-21.7406311, 9.70659542, 15]
|
||||
Rotation: [0.999910355, -0.0133911213, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.BasicController
|
||||
StoredFields:
|
||||
- Name: Speed
|
||||
Type: 1
|
||||
Data: 12
|
||||
CameraComponent:
|
||||
Camera: some camera data...
|
||||
Primary: true
|
||||
- Entity: 1289165777996378215
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [500, 0, 0]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [1200, 1, 5]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 0
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [600, 0.5]
|
||||
Density: 1
|
||||
Friction: 2
|
||||
- Entity: 14057422478420564497
|
||||
TagComponent:
|
||||
Tag: Player
|
||||
TransformComponent:
|
||||
Position: [-23.6932545, 1.59184527, -1.96369365e-06]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.PlayerCube
|
||||
StoredFields:
|
||||
- Name: HorizontalForce
|
||||
Type: 1
|
||||
Data: 0.5
|
||||
- Name: MaxSpeed
|
||||
Type: 5
|
||||
Data: [7, 10]
|
||||
- Name: JumpForce
|
||||
Type: 1
|
||||
Data: 3
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Sphere1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 29.2000008
|
||||
CircleCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Radius: 0.5
|
||||
Density: 1
|
||||
Friction: 1
|
||||
- Entity: 1352995477042327524
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-29.6808929, 29.7597198, 0]
|
||||
Rotation: [0.707106769, 0, 0, 0.707106769]
|
||||
Scale: [58.4179001, 4.47999144, 4.48000002]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 0
|
||||
Mass: 3
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [29.7000008, 2.24000001]
|
||||
Density: 1
|
||||
Friction: 1
|
||||
- Entity: 15223077898852293773
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [6.12674046, 45.5617676, 0]
|
||||
Rotation: [0.977883637, 0, 0, -0.209149584]
|
||||
Scale: [4.47999668, 4.47999668, 4.48000002]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [2.24000001, 2.24000001]
|
||||
Density: 1
|
||||
Friction: 1
|
||||
- Entity: 5421735812495444456
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-20.766222, 2.29431438, 0]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [3.00000024, 0.300000012, 1]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 0
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [1.5, 0.150000006]
|
||||
Density: 1
|
||||
Friction: 1
|
||||
- Entity: 2842299641876190180
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-16.6143265, 4.39151001, 6.43359499e-09]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [3.00000024, 0.300000012, 1]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 0
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [1.5, 0.150000006]
|
||||
Density: 1
|
||||
Friction: 1
|
||||
@ -1,6 +1,6 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetPath: assets/env/pink_sunrise_4k.hdr
|
||||
AssetPath: assets\env\birchwood_4k.hdr
|
||||
Light:
|
||||
Direction: [-0.787, -0.733, 1]
|
||||
Radiance: [1, 1, 1]
|
||||
@ -51,6 +51,7 @@ Entities:
|
||||
Bounciness: 0.1
|
||||
MeshColliderComponent:
|
||||
AssetPath: assets/meshes/Capsule.fbx
|
||||
IsConvex: true
|
||||
IsTrigger: false
|
||||
- Entity: 11149966982516343187
|
||||
TagComponent:
|
||||
@ -79,6 +80,7 @@ Entities:
|
||||
Bounciness: 0.1
|
||||
MeshColliderComponent:
|
||||
AssetPath: assets/meshes/Sphere1m.fbx
|
||||
IsConvex: true
|
||||
IsTrigger: false
|
||||
- Entity: 10169503531257462571
|
||||
TagComponent:
|
||||
@ -176,6 +178,17 @@ Entities:
|
||||
Offset: [0, 0, 0]
|
||||
Size: [1, 1, 1]
|
||||
IsTrigger: false
|
||||
- Entity: 2025484417758554619
|
||||
TagComponent:
|
||||
Tag: Sky Light
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
SkyLightComponent:
|
||||
EnvironmentAssetPath: assets\env\birchwood_4k.hdr
|
||||
Intensity: 1
|
||||
Angle: 0
|
||||
PhysicsLayers:
|
||||
- Name: Box
|
||||
CollidesWith:
|
||||
|
||||
@ -1,174 +0,0 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetPath: assets/env/pink_sunrise_4k.hdr
|
||||
Light:
|
||||
Direction: [-0.787, -0.73299998, 1]
|
||||
Radiance: [1, 1, 1]
|
||||
Multiplier: 0.514999986
|
||||
Entities:
|
||||
- Entity: 15861629587505754
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-18.2095661, 39.2518234, 0]
|
||||
Rotation: [0.967056513, 0, 0, -0.254561812]
|
||||
Scale: [4.47999525, 4.47999525, 4.48000002]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [2.24000001, 2.24000001]
|
||||
- Entity: 15223077898852293773
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [5.37119865, 43.8762894, 0]
|
||||
Rotation: [0.977883637, 0, 0, -0.209149718]
|
||||
Scale: [4.47999668, 4.47999668, 4.48000002]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [2.24000001, 2.24000001]
|
||||
- Entity: 2157107598622182863
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-7.60411549, 44.1442184, 0]
|
||||
Rotation: [0.989285827, 0, 0, 0.145991713]
|
||||
Scale: [4.47999287, 4.47999287, 4.48000002]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 0.5
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [2.24000001, 2.24000001]
|
||||
- Entity: 8080964283681139153
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-0.739211679, 37.7653275, 0]
|
||||
Rotation: [0.956475914, 0, 0, -0.291811317]
|
||||
Scale: [5, 2, 2]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 0.25
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [2.5, 1]
|
||||
- Entity: 1352995477042327524
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-8.32969856, 30.4078159, 0]
|
||||
Rotation: [0.781595349, 0, 0, 0.623785794]
|
||||
Scale: [14.000001, 4.47999334, 4.48000002]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 3
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [7, 2.24000001]
|
||||
- Entity: 935615878363259513
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [6.88031197, 31.942337, 0]
|
||||
Rotation: [0.986578286, 0, 0, 0.163288936]
|
||||
Scale: [4.47999954, 4.47999954, 4.48000002]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [2.24000001, 2.24000001]
|
||||
- Entity: 14057422478420564497
|
||||
TagComponent:
|
||||
Tag: Player
|
||||
TransformComponent:
|
||||
Position: [0, 22.774044, 0]
|
||||
Rotation: [0.942591429, 0, 0, -0.333948225]
|
||||
Scale: [6.00000048, 6.00000048, 4.48000002]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.PlayerCube
|
||||
StoredFields:
|
||||
- Name: HorizontalForce
|
||||
Type: 1
|
||||
Data: 10
|
||||
- Name: VerticalForce
|
||||
Type: 1
|
||||
Data: 10
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Sphere1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
CircleCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Radius: 3
|
||||
- Entity: 1289165777996378215
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [50, 1, 50]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.Sink
|
||||
StoredFields:
|
||||
- Name: SinkSpeed
|
||||
Type: 1
|
||||
Data: 0
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 0
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [25, 0.5]
|
||||
- Entity: 5178862374589434728
|
||||
TagComponent:
|
||||
Tag: Camera
|
||||
TransformComponent:
|
||||
Position: [0, 25, 79.75]
|
||||
Rotation: [0.995602965, -0.0936739072, 0, 0]
|
||||
Scale: [1, 0.999999821, 0.999999821]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.BasicController
|
||||
StoredFields:
|
||||
- Name: Speed
|
||||
Type: 1
|
||||
Data: 12
|
||||
CameraComponent:
|
||||
Camera: some camera data...
|
||||
Primary: true
|
||||
- Entity: 3948844418381294888
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-1.48028564, 49.5945244, -2.38418579e-07]
|
||||
Rotation: [0.977883637, 0, 0, -0.209149733]
|
||||
Scale: [1.99999976, 1.99999976, 2]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [1, 1]
|
||||
@ -1,119 +0,0 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetPath: assets/env/pink_sunrise_4k.hdr
|
||||
Light:
|
||||
Direction: [-0.787, -0.73299998, 1]
|
||||
Radiance: [1, 1, 1]
|
||||
Multiplier: 0.514999986
|
||||
Entities:
|
||||
- Entity: 10169503531257462571
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [0, 1.5, 0]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [2, 2, 2]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBodyComponent:
|
||||
BodyType: 1
|
||||
Mass: 0.5
|
||||
IsKinematic: false
|
||||
Constraints:
|
||||
LockPositionX: false
|
||||
LockPositionY: false
|
||||
LockPositionZ: false
|
||||
LockRotationX: true
|
||||
LockRotationY: true
|
||||
LockRotationZ: true
|
||||
PhysicsMaterialComponent:
|
||||
StaticFriction: 1
|
||||
DynamicFriction: 1
|
||||
Bounciness: 0
|
||||
BoxColliderComponent:
|
||||
Offset: [0, 0, 0]
|
||||
Size: [2, 2, 2]
|
||||
- Entity: 14057422478420564497
|
||||
TagComponent:
|
||||
Tag: Player
|
||||
TransformComponent:
|
||||
Position: [-19.43363, 4.50874043, -1.96695328e-06]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.PlayerSphere
|
||||
StoredFields:
|
||||
- Name: HorizontalForce
|
||||
Type: 1
|
||||
Data: 10
|
||||
- Name: MaxSpeed
|
||||
Type: 6
|
||||
Data: [10, 10, 10]
|
||||
- Name: JumpForce
|
||||
Type: 1
|
||||
Data: 200
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Sphere1m.fbx
|
||||
RigidBodyComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
IsKinematic: false
|
||||
Constraints:
|
||||
LockPositionX: false
|
||||
LockPositionY: false
|
||||
LockPositionZ: false
|
||||
LockRotationX: true
|
||||
LockRotationY: true
|
||||
LockRotationZ: true
|
||||
PhysicsMaterialComponent:
|
||||
StaticFriction: 1
|
||||
DynamicFriction: 1
|
||||
Bounciness: 0
|
||||
SphereColliderComponent:
|
||||
Radius: 0.5
|
||||
- Entity: 5178862374589434728
|
||||
TagComponent:
|
||||
Tag: Camera
|
||||
TransformComponent:
|
||||
Position: [-21.7406311, 9.70659542, 15]
|
||||
Rotation: [0.999910355, -0.0133911213, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.BasicController
|
||||
StoredFields:
|
||||
- Name: Speed
|
||||
Type: 1
|
||||
Data: 12
|
||||
- Name: DistanceFromPlayer
|
||||
Type: 1
|
||||
Data: 15
|
||||
CameraComponent:
|
||||
Camera: some camera data...
|
||||
Primary: true
|
||||
- Entity: 18306113171518048249
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [50, 1, 50]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBodyComponent:
|
||||
BodyType: 0
|
||||
Mass: 1
|
||||
IsKinematic: false
|
||||
Constraints:
|
||||
LockPositionX: false
|
||||
LockPositionY: false
|
||||
LockPositionZ: false
|
||||
LockRotationX: true
|
||||
LockRotationY: true
|
||||
LockRotationZ: true
|
||||
PhysicsMaterialComponent:
|
||||
StaticFriction: 1
|
||||
DynamicFriction: 1
|
||||
Bounciness: 0
|
||||
BoxColliderComponent:
|
||||
Offset: [0, 0, 0]
|
||||
Size: [50, 1, 50]
|
||||
@ -1,66 +0,0 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetPath: assets/env/birchwood_4k.hdr
|
||||
Light:
|
||||
Direction: [-0.5, -0.5, 1]
|
||||
Radiance: [1, 1, 1]
|
||||
Multiplier: 1
|
||||
Entities:
|
||||
- Entity: 1289165777996378215
|
||||
TagComponent:
|
||||
Tag: Sphere
|
||||
TransformComponent:
|
||||
Position: [0, 21.9805069, -1.64006281]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [0.100000024, 0.100000024, 0.100000024]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.Sink
|
||||
StoredFields:
|
||||
- Name: SinkSpeed
|
||||
Type: 1
|
||||
Data: 5
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Sphere1m.fbx
|
||||
- Entity: 5178862374589434728
|
||||
TagComponent:
|
||||
Tag: Camera
|
||||
TransformComponent:
|
||||
Position: [0, 14.75, 79.75]
|
||||
Rotation: [0.995602965, -0.0936739072, 0, 0]
|
||||
Scale: [1, 0.999999821, 0.999999821]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.BasicController
|
||||
StoredFields:
|
||||
- Name: Speed
|
||||
Type: 1
|
||||
Data: 12
|
||||
CameraComponent:
|
||||
Camera: some camera data...
|
||||
Primary: true
|
||||
- Entity: 9095450049242347594
|
||||
TagComponent:
|
||||
Tag: Test Entity
|
||||
TransformComponent:
|
||||
Position: [0.248109579, -1.90734863e-06, -0.268640995]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.Script
|
||||
StoredFields:
|
||||
- Name: VerticalSpeed
|
||||
Type: 1
|
||||
Data: 0
|
||||
- Name: SinkRate
|
||||
Type: 1
|
||||
Data: 0
|
||||
- Name: Speed
|
||||
Type: 1
|
||||
Data: 1
|
||||
- Name: Rotation
|
||||
Type: 1
|
||||
Data: 0
|
||||
- Name: Velocity
|
||||
Type: 6
|
||||
Data: [0, 0, 0]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/TestScene.fbx
|
||||
63
Editor/assets/shaders/BloomBlend.glsl
Normal file
63
Editor/assets/shaders/BloomBlend.glsl
Normal file
@ -0,0 +1,63 @@
|
||||
#type vertex
|
||||
#version 430
|
||||
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
layout(location = 1) in vec2 a_TexCoord;
|
||||
|
||||
out vec2 v_TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 position = vec4(a_Position.xy, 0.0, 1.0);
|
||||
v_TexCoord = a_TexCoord;
|
||||
gl_Position = position;
|
||||
}
|
||||
|
||||
#type fragment
|
||||
#version 430
|
||||
|
||||
layout(location = 0) out vec4 o_Color;
|
||||
|
||||
in vec2 v_TexCoord;
|
||||
|
||||
uniform sampler2D u_SceneTexture;
|
||||
uniform sampler2D u_BloomTexture;
|
||||
|
||||
uniform float u_Exposure;
|
||||
uniform bool u_EnableBloom;
|
||||
|
||||
void main()
|
||||
{
|
||||
#if 1
|
||||
const float gamma = 2.2;
|
||||
const float pureWhite = 1.0;
|
||||
|
||||
// Tonemapping
|
||||
vec3 color = texture(u_SceneTexture, v_TexCoord).rgb;
|
||||
if (u_EnableBloom)
|
||||
{
|
||||
vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
|
||||
color += bloomColor;
|
||||
}
|
||||
|
||||
// Reinhard tonemapping
|
||||
float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
|
||||
float mappedLuminance = (luminance * (1.0 + luminance / (pureWhite * pureWhite))) / (1.0 + luminance);
|
||||
|
||||
// Scale color by ratio of average luminances.
|
||||
vec3 mappedColor = (mappedLuminance / luminance) * color* u_Exposure;
|
||||
|
||||
// Gamma correction.
|
||||
o_Color = vec4(color, 1.0);
|
||||
#else
|
||||
const float gamma = 2.2;
|
||||
vec3 hdrColor = texture(u_SceneTexture, v_TexCoord).rgb;
|
||||
vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
|
||||
hdrColor += bloomColor; // additive blending
|
||||
// tone mapping
|
||||
vec3 result = vec3(1.0) - exp(-hdrColor * u_Exposure);
|
||||
// also gamma correct while we're at it
|
||||
result = pow(result, vec3(1.0 / gamma));
|
||||
o_Color = vec4(result, 1.0);
|
||||
#endif
|
||||
}
|
||||
79
Editor/assets/shaders/BloomBlur.glsl
Normal file
79
Editor/assets/shaders/BloomBlur.glsl
Normal file
@ -0,0 +1,79 @@
|
||||
#type vertex
|
||||
#version 430
|
||||
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
layout(location = 1) in vec2 a_TexCoord;
|
||||
|
||||
out vec2 v_TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 position = vec4(a_Position.xy, 0.0, 1.0);
|
||||
v_TexCoord = a_TexCoord;
|
||||
gl_Position = position;
|
||||
}
|
||||
|
||||
#type fragment
|
||||
#version 430
|
||||
|
||||
layout(location = 0) out vec4 o_Color;
|
||||
|
||||
in vec2 v_TexCoord;
|
||||
|
||||
uniform sampler2D u_Texture;
|
||||
uniform bool u_Horizontal;
|
||||
|
||||
void main()
|
||||
{
|
||||
#if 1
|
||||
// From learnopengl.com
|
||||
float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
|
||||
|
||||
vec2 tex_offset = 1.0 / textureSize(u_Texture, 0); // gets size of single texel
|
||||
vec3 result = texture(u_Texture, v_TexCoord).rgb * weight[0]; // current fragment's contribution
|
||||
if (u_Horizontal)
|
||||
{
|
||||
for(int i = 1; i < 5; ++i)
|
||||
{
|
||||
result += texture(u_Texture, v_TexCoord + vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
|
||||
result += texture(u_Texture, v_TexCoord - vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 1; i < 5; ++i)
|
||||
{
|
||||
result += texture(u_Texture, v_TexCoord + vec2(0.0, tex_offset.y * i)).rgb * weight[i];
|
||||
result += texture(u_Texture, v_TexCoord - vec2(0.0, tex_offset.y * i)).rgb * weight[i];
|
||||
}
|
||||
}
|
||||
o_Color = vec4(result, 1.0);
|
||||
#else
|
||||
// From https://www.shadertoy.com/view/Xltfzj
|
||||
|
||||
float Pi = 6.28318530718; // Pi*2
|
||||
|
||||
// GAUSSIAN BLUR SETTINGS {{{
|
||||
float Directions =32.0; // BLUR DIRECTIONS (Default 16.0 - More is better but slower)
|
||||
float Quality = 6.0; // BLUR QUALITY (Default 4.0 - More is better but slower)
|
||||
float Size = 16.0; // BLUR SIZE (Radius)
|
||||
// GAUSSIAN BLUR SETTINGS }}}
|
||||
|
||||
vec2 Radius = Size/textureSize(u_Texture, 0);
|
||||
|
||||
vec3 result = texture(u_Texture, v_TexCoord).rgb;
|
||||
vec2 uv = v_TexCoord;
|
||||
// Blur calculations
|
||||
for( float d=0.0; d<Pi; d+=Pi/Directions)
|
||||
{
|
||||
for(float i=1.0/Quality; i<=1.0; i+=1.0/Quality)
|
||||
{
|
||||
result += texture( u_Texture, uv+vec2(cos(d),sin(d))*Radius*i).rgb;
|
||||
}
|
||||
}
|
||||
|
||||
// Output to screen
|
||||
result /= Quality * Directions - 15.0;
|
||||
o_Color = vec4(result, 1.0);
|
||||
#endif
|
||||
}
|
||||
@ -4,13 +4,10 @@
|
||||
#version 430
|
||||
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
layout(location = 1) in vec2 a_TexCoord;
|
||||
|
||||
uniform mat4 u_ViewProjection;
|
||||
uniform mat4 u_Transform;
|
||||
|
||||
out vec2 v_TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
|
||||
|
||||
36
Editor/assets/shaders/Outline_Anim.glsl
Normal file
36
Editor/assets/shaders/Outline_Anim.glsl
Normal file
@ -0,0 +1,36 @@
|
||||
// Outline Shader
|
||||
|
||||
#type vertex
|
||||
#version 430
|
||||
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
|
||||
layout(location = 5) in ivec4 a_BoneIndices;
|
||||
layout(location = 6) in vec4 a_BoneWeights;
|
||||
|
||||
uniform mat4 u_ViewProjection;
|
||||
uniform mat4 u_Transform;
|
||||
|
||||
const int MAX_BONES = 100;
|
||||
uniform mat4 u_BoneTransforms[100];
|
||||
|
||||
void main()
|
||||
{
|
||||
mat4 boneTransform = u_BoneTransforms[a_BoneIndices[0]] * a_BoneWeights[0];
|
||||
boneTransform += u_BoneTransforms[a_BoneIndices[1]] * a_BoneWeights[1];
|
||||
boneTransform += u_BoneTransforms[a_BoneIndices[2]] * a_BoneWeights[2];
|
||||
boneTransform += u_BoneTransforms[a_BoneIndices[3]] * a_BoneWeights[3];
|
||||
|
||||
vec4 localPosition = boneTransform * vec4(a_Position, 1.0);
|
||||
gl_Position = u_ViewProjection * u_Transform * localPosition;
|
||||
}
|
||||
|
||||
#type fragment
|
||||
#version 430
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0, 0.5, 0.0, 1.0);
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
// -----------------------------
|
||||
// -- From Hazel Engine PBR shader --
|
||||
// -- Hazel Engine PBR shader --
|
||||
// -----------------------------
|
||||
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
||||
// Currently heavily updated.
|
||||
// Currently heavily updated.
|
||||
//
|
||||
// References upon which this is based:
|
||||
// - Unreal Engine 4 PBR notes (https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf)
|
||||
@ -22,34 +22,50 @@ layout(location = 5) in ivec4 a_BoneIndices;
|
||||
layout(location = 6) in vec4 a_BoneWeights;
|
||||
|
||||
uniform mat4 u_ViewProjectionMatrix;
|
||||
uniform mat4 u_ViewMatrix;
|
||||
uniform mat4 u_Transform;
|
||||
|
||||
uniform mat4 u_LightMatrixCascade0;
|
||||
uniform mat4 u_LightMatrixCascade1;
|
||||
uniform mat4 u_LightMatrixCascade2;
|
||||
uniform mat4 u_LightMatrixCascade3;
|
||||
|
||||
const int MAX_BONES = 100;
|
||||
uniform mat4 u_BoneTransforms[100];
|
||||
|
||||
out VertexOutput
|
||||
{
|
||||
vec3 WorldPosition;
|
||||
vec3 Normal;
|
||||
vec3 Normal;
|
||||
vec2 TexCoord;
|
||||
mat3 WorldNormals;
|
||||
mat3 WorldTransform;
|
||||
vec3 Binormal;
|
||||
vec4 ShadowMapCoords[4];
|
||||
vec3 ViewPosition;
|
||||
} vs_Output;
|
||||
|
||||
void main()
|
||||
{
|
||||
mat4 boneTransform = u_BoneTransforms[a_BoneIndices[0]] * a_BoneWeights[0];
|
||||
boneTransform += u_BoneTransforms[a_BoneIndices[1]] * a_BoneWeights[1];
|
||||
boneTransform += u_BoneTransforms[a_BoneIndices[2]] * a_BoneWeights[2];
|
||||
boneTransform += u_BoneTransforms[a_BoneIndices[3]] * a_BoneWeights[3];
|
||||
mat4 boneTransform = u_BoneTransforms[a_BoneIndices[0]] * a_BoneWeights[0];
|
||||
boneTransform += u_BoneTransforms[a_BoneIndices[1]] * a_BoneWeights[1];
|
||||
boneTransform += u_BoneTransforms[a_BoneIndices[2]] * a_BoneWeights[2];
|
||||
boneTransform += u_BoneTransforms[a_BoneIndices[3]] * a_BoneWeights[3];
|
||||
|
||||
vec4 localPosition = boneTransform * vec4(a_Position, 1.0);
|
||||
|
||||
vs_Output.WorldPosition = vec3(u_Transform * boneTransform * vec4(a_Position, 1.0));
|
||||
vs_Output.Normal = mat3(u_Transform) * mat3(boneTransform) * a_Normal;
|
||||
vs_Output.Normal = mat3(u_Transform) * mat3(boneTransform) * a_Normal;
|
||||
vs_Output.TexCoord = vec2(a_TexCoord.x, 1.0 - a_TexCoord.y);
|
||||
vs_Output.WorldNormals = mat3(u_Transform) * mat3(a_Tangent, a_Binormal, a_Normal);
|
||||
vs_Output.Binormal = mat3(boneTransform) * a_Binormal;
|
||||
vs_Output.WorldTransform = mat3(u_Transform);
|
||||
vs_Output.Binormal = a_Binormal;
|
||||
|
||||
vs_Output.ShadowMapCoords[0] = u_LightMatrixCascade0 * vec4(vs_Output.WorldPosition, 1.0);
|
||||
vs_Output.ShadowMapCoords[1] = u_LightMatrixCascade1 * vec4(vs_Output.WorldPosition, 1.0);
|
||||
vs_Output.ShadowMapCoords[2] = u_LightMatrixCascade2 * vec4(vs_Output.WorldPosition, 1.0);
|
||||
vs_Output.ShadowMapCoords[3] = u_LightMatrixCascade3 * vec4(vs_Output.WorldPosition, 1.0);
|
||||
vs_Output.ViewPosition = vec3(u_ViewMatrix * vec4(vs_Output.WorldPosition, 1.0));
|
||||
|
||||
gl_Position = u_ViewProjectionMatrix * u_Transform * localPosition;
|
||||
}
|
||||
@ -65,7 +81,8 @@ const int LightCount = 1;
|
||||
// Constant normal incidence Fresnel factor for all dielectrics.
|
||||
const vec3 Fdielectric = vec3(0.04);
|
||||
|
||||
struct Light {
|
||||
struct DirectionalLight
|
||||
{
|
||||
vec3 Direction;
|
||||
vec3 Radiance;
|
||||
float Multiplier;
|
||||
@ -74,15 +91,19 @@ struct Light {
|
||||
in VertexOutput
|
||||
{
|
||||
vec3 WorldPosition;
|
||||
vec3 Normal;
|
||||
vec3 Normal;
|
||||
vec2 TexCoord;
|
||||
mat3 WorldNormals;
|
||||
mat3 WorldTransform;
|
||||
vec3 Binormal;
|
||||
vec4 ShadowMapCoords[4];
|
||||
vec3 ViewPosition;
|
||||
} vs_Input;
|
||||
|
||||
layout(location=0) out vec4 color;
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(location = 1) out vec4 o_BloomColor;
|
||||
|
||||
uniform Light lights;
|
||||
uniform DirectionalLight u_DirectionalLights;
|
||||
uniform vec3 u_CameraPosition;
|
||||
|
||||
// PBR texture inputs
|
||||
@ -98,6 +119,25 @@ uniform samplerCube u_EnvIrradianceTex;
|
||||
// BRDF LUT
|
||||
uniform sampler2D u_BRDFLUTTexture;
|
||||
|
||||
// PCSS
|
||||
uniform sampler2D u_ShadowMapTexture[4];
|
||||
uniform mat4 u_LightView;
|
||||
uniform bool u_ShowCascades;
|
||||
uniform bool u_SoftShadows;
|
||||
uniform float u_LightSize;
|
||||
uniform float u_MaxShadowDistance;
|
||||
uniform float u_ShadowFade;
|
||||
uniform bool u_CascadeFading;
|
||||
uniform float u_CascadeTransitionFade;
|
||||
|
||||
uniform vec4 u_CascadeSplits;
|
||||
|
||||
uniform float u_IBLContribution;
|
||||
|
||||
uniform float u_BloomThreshold;
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
uniform vec3 u_AlbedoColor;
|
||||
uniform float u_Metalness;
|
||||
uniform float u_Roughness;
|
||||
@ -105,7 +145,6 @@ uniform float u_Roughness;
|
||||
uniform float u_EnvMapRotation;
|
||||
|
||||
// Toggles
|
||||
uniform float u_RadiancePrefilter;
|
||||
uniform float u_AlbedoTexToggle;
|
||||
uniform float u_NormalTexToggle;
|
||||
uniform float u_MetalnessTexToggle;
|
||||
@ -151,23 +190,23 @@ float gaSchlickGGX(float cosLi, float NdotV, float roughness)
|
||||
|
||||
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||
{
|
||||
float r = (roughness + 1.0);
|
||||
float k = (r*r) / 8.0;
|
||||
float r = (roughness + 1.0);
|
||||
float k = (r*r) / 8.0;
|
||||
|
||||
float nom = NdotV;
|
||||
float denom = NdotV * (1.0 - k) + k;
|
||||
float nom = NdotV;
|
||||
float denom = NdotV * (1.0 - k) + k;
|
||||
|
||||
return nom / denom;
|
||||
return nom / denom;
|
||||
}
|
||||
|
||||
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||
{
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||
|
||||
return ggx1 * ggx2;
|
||||
return ggx1 * ggx2;
|
||||
}
|
||||
|
||||
// Shlick's approximation of the Fresnel factor.
|
||||
@ -178,26 +217,26 @@ vec3 fresnelSchlick(vec3 F0, float cosTheta)
|
||||
|
||||
vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
|
||||
{
|
||||
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
||||
}
|
||||
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------
|
||||
// The following code (from Unreal Engine 4's paper) shows how to filter the environment map
|
||||
// for different roughnesses. This is mean to be computed offline and stored in cube map mips,
|
||||
// so turning this on online will cause poor performance
|
||||
float RadicalInverse_VdC(uint bits)
|
||||
float RadicalInverse_VdC(uint bits)
|
||||
{
|
||||
bits = (bits << 16u) | (bits >> 16u);
|
||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||
bits = (bits << 16u) | (bits >> 16u);
|
||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||
}
|
||||
|
||||
vec2 Hammersley(uint i, uint N)
|
||||
{
|
||||
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
|
||||
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
|
||||
}
|
||||
|
||||
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N)
|
||||
@ -244,11 +283,11 @@ vec3 PrefilterEnvMap(float Roughness, vec3 R)
|
||||
|
||||
vec3 RotateVectorAboutY(float angle, vec3 vec)
|
||||
{
|
||||
angle = radians(angle);
|
||||
mat3x3 rotationMatrix ={vec3(cos(angle),0.0,sin(angle)),
|
||||
vec3(0.0,1.0,0.0),
|
||||
vec3(-sin(angle),0.0,cos(angle))};
|
||||
return rotationMatrix * vec;
|
||||
angle = radians(angle);
|
||||
mat3x3 rotationMatrix ={vec3(cos(angle),0.0,sin(angle)),
|
||||
vec3(0.0,1.0,0.0),
|
||||
vec3(-sin(angle),0.0,cos(angle))};
|
||||
return rotationMatrix * vec;
|
||||
}
|
||||
|
||||
vec3 Lighting(vec3 F0)
|
||||
@ -256,8 +295,8 @@ vec3 Lighting(vec3 F0)
|
||||
vec3 result = vec3(0.0);
|
||||
for(int i = 0; i < LightCount; i++)
|
||||
{
|
||||
vec3 Li = -lights.Direction;
|
||||
vec3 Lradiance = lights.Radiance * lights.Multiplier;
|
||||
vec3 Li = u_DirectionalLights.Direction;
|
||||
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Multiplier;
|
||||
vec3 Lh = normalize(Li + m_Params.View);
|
||||
|
||||
// Calculate angles between surface normal and various light vectors.
|
||||
@ -298,13 +337,188 @@ vec3 IBL(vec3 F0, vec3 Lr)
|
||||
return kd * diffuseIBL + specularIBL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// PCSS
|
||||
/////////////////////////////////////////////
|
||||
|
||||
uint CascadeIndex = 0;
|
||||
float ShadowFade = 1.0;
|
||||
|
||||
float GetShadowBias()
|
||||
{
|
||||
const float MINIMUM_SHADOW_BIAS = 0.002;
|
||||
float bias = max(MINIMUM_SHADOW_BIAS * (1.0 - dot(m_Params.Normal, u_DirectionalLights.Direction)), MINIMUM_SHADOW_BIAS);
|
||||
return bias;
|
||||
}
|
||||
|
||||
float HardShadows_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords)
|
||||
{
|
||||
float bias = GetShadowBias();
|
||||
float z = texture(shadowMap, shadowCoords.xy).x;
|
||||
return 1.0 - step(z + bias, shadowCoords.z) * ShadowFade;
|
||||
}
|
||||
|
||||
// Penumbra
|
||||
|
||||
// this search area estimation comes from the following article:
|
||||
// http://developer.download.nvidia.com/whitepapers/2008/PCSS_DirectionalLight_Integration.pdf
|
||||
float SearchWidth(float uvLightSize, float receiverDistance)
|
||||
{
|
||||
const float NEAR = 0.1;
|
||||
return uvLightSize * (receiverDistance - NEAR) / u_CameraPosition.z;
|
||||
}
|
||||
|
||||
float u_light_zNear = 0.0; // 0.01 gives artifacts? maybe because of ortho proj?
|
||||
float u_light_zFar = 10000.0;
|
||||
vec2 u_lightRadiusUV = vec2(0.05);
|
||||
|
||||
vec2 searchRegionRadiusUV(float zWorld)
|
||||
{
|
||||
return u_lightRadiusUV * (zWorld - u_light_zNear) / zWorld;
|
||||
}
|
||||
|
||||
const vec2 PoissonDistribution[64] = vec2[](
|
||||
vec2(-0.884081, 0.124488),
|
||||
vec2(-0.714377, 0.027940),
|
||||
vec2(-0.747945, 0.227922),
|
||||
vec2(-0.939609, 0.243634),
|
||||
vec2(-0.985465, 0.045534),
|
||||
vec2(-0.861367, -0.136222),
|
||||
vec2(-0.881934, 0.396908),
|
||||
vec2(-0.466938, 0.014526),
|
||||
vec2(-0.558207, 0.212662),
|
||||
vec2(-0.578447, -0.095822),
|
||||
vec2(-0.740266, -0.095631),
|
||||
vec2(-0.751681, 0.472604),
|
||||
vec2(-0.553147, -0.243177),
|
||||
vec2(-0.674762, -0.330730),
|
||||
vec2(-0.402765, -0.122087),
|
||||
vec2(-0.319776, -0.312166),
|
||||
vec2(-0.413923, -0.439757),
|
||||
vec2(-0.979153, -0.201245),
|
||||
vec2(-0.865579, -0.288695),
|
||||
vec2(-0.243704, -0.186378),
|
||||
vec2(-0.294920, -0.055748),
|
||||
vec2(-0.604452, -0.544251),
|
||||
vec2(-0.418056, -0.587679),
|
||||
vec2(-0.549156, -0.415877),
|
||||
vec2(-0.238080, -0.611761),
|
||||
vec2(-0.267004, -0.459702),
|
||||
vec2(-0.100006, -0.229116),
|
||||
vec2(-0.101928, -0.380382),
|
||||
vec2(-0.681467, -0.700773),
|
||||
vec2(-0.763488, -0.543386),
|
||||
vec2(-0.549030, -0.750749),
|
||||
vec2(-0.809045, -0.408738),
|
||||
vec2(-0.388134, -0.773448),
|
||||
vec2(-0.429392, -0.894892),
|
||||
vec2(-0.131597, 0.065058),
|
||||
vec2(-0.275002, 0.102922),
|
||||
vec2(-0.106117, -0.068327),
|
||||
vec2(-0.294586, -0.891515),
|
||||
vec2(-0.629418, 0.379387),
|
||||
vec2(-0.407257, 0.339748),
|
||||
vec2(0.071650, -0.384284),
|
||||
vec2(0.022018, -0.263793),
|
||||
vec2(0.003879, -0.136073),
|
||||
vec2(-0.137533, -0.767844),
|
||||
vec2(-0.050874, -0.906068),
|
||||
vec2(0.114133, -0.070053),
|
||||
vec2(0.163314, -0.217231),
|
||||
vec2(-0.100262, -0.587992),
|
||||
vec2(-0.004942, 0.125368),
|
||||
vec2(0.035302, -0.619310),
|
||||
vec2(0.195646, -0.459022),
|
||||
vec2(0.303969, -0.346362),
|
||||
vec2(-0.678118, 0.685099),
|
||||
vec2(-0.628418, 0.507978),
|
||||
vec2(-0.508473, 0.458753),
|
||||
vec2(0.032134, -0.782030),
|
||||
vec2(0.122595, 0.280353),
|
||||
vec2(-0.043643, 0.312119),
|
||||
vec2(0.132993, 0.085170),
|
||||
vec2(-0.192106, 0.285848),
|
||||
vec2(0.183621, -0.713242),
|
||||
vec2(0.265220, -0.596716),
|
||||
vec2(-0.009628, -0.483058),
|
||||
vec2(-0.018516, 0.435703)
|
||||
);
|
||||
|
||||
vec2 SamplePoisson(int index)
|
||||
{
|
||||
return PoissonDistribution[index % 64];
|
||||
}
|
||||
|
||||
float FindBlockerDistance_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords, float uvLightSize)
|
||||
{
|
||||
float bias = GetShadowBias();
|
||||
|
||||
int numBlockerSearchSamples = 64;
|
||||
int blockers = 0;
|
||||
float avgBlockerDistance = 0;
|
||||
|
||||
float zEye = -(u_LightView * vec4(vs_Input.WorldPosition, 1.0)).z;
|
||||
vec2 searchWidth = searchRegionRadiusUV(zEye);
|
||||
for (int i = 0; i < numBlockerSearchSamples; i++)
|
||||
{
|
||||
float z = texture(shadowMap, shadowCoords.xy + SamplePoisson(i) * searchWidth).r;
|
||||
if (z < (shadowCoords.z - bias))
|
||||
{
|
||||
blockers++;
|
||||
avgBlockerDistance += z;
|
||||
}
|
||||
}
|
||||
|
||||
if (blockers > 0)
|
||||
return avgBlockerDistance / float(blockers);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
float PenumbraWidth(sampler2D shadowMap, vec3 shadowCoords, float uvLightSize)
|
||||
{
|
||||
float blockerDistance = FindBlockerDistance_DirectionalLight(shadowMap, shadowCoords, uvLightSize);
|
||||
if (blockerDistance == -1)
|
||||
return -1;
|
||||
|
||||
return (shadowCoords.z - blockerDistance) / blockerDistance;
|
||||
}
|
||||
|
||||
float PCF_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords, float uvRadius)
|
||||
{
|
||||
float bias = GetShadowBias();
|
||||
int numPCFSamples = 64;
|
||||
float sum = 0;
|
||||
for (int i = 0; i < numPCFSamples; i++)
|
||||
{
|
||||
float z = texture(shadowMap, shadowCoords.xy + SamplePoisson(i) * uvRadius).r;
|
||||
sum += (z < (shadowCoords.z - bias)) ? 1 : 0;
|
||||
}
|
||||
return sum / numPCFSamples;
|
||||
}
|
||||
|
||||
float PCSS_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords, float uvLightSize)
|
||||
{
|
||||
float blockerDistance = FindBlockerDistance_DirectionalLight(shadowMap, shadowCoords, uvLightSize);
|
||||
if (blockerDistance == -1)
|
||||
return 1;
|
||||
|
||||
float penumbraWidth = (shadowCoords.z - blockerDistance) / blockerDistance;
|
||||
|
||||
float NEAR = 0.01; // Should this value be tweakable?
|
||||
float uvRadius = penumbraWidth * uvLightSize * NEAR / shadowCoords.z;
|
||||
return 1.0 - PCF_DirectionalLight(shadowMap, shadowCoords, uvRadius) * ShadowFade;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
||||
void main()
|
||||
{
|
||||
// Standard PBR inputs
|
||||
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
|
||||
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
|
||||
m_Params.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness;
|
||||
m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
|
||||
m_Params.Roughness = max(m_Params.Roughness, 0.05); // Minimum roughness of 0.05 to keep specular highlight
|
||||
m_Params.Roughness = max(m_Params.Roughness, 0.05); // Minimum roughness of 0.05 to keep specular highlight
|
||||
|
||||
// Normals (either from vertex or map)
|
||||
m_Params.Normal = normalize(vs_Input.Normal);
|
||||
@ -316,15 +530,109 @@ void main()
|
||||
|
||||
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
|
||||
m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0);
|
||||
|
||||
|
||||
// Specular reflection vector
|
||||
vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View;
|
||||
|
||||
// Fresnel reflectance, metals use albedo
|
||||
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
|
||||
|
||||
vec3 lightContribution = Lighting(F0);
|
||||
vec3 iblContribution = IBL(F0, Lr);
|
||||
const uint SHADOW_MAP_CASCADE_COUNT = 4;
|
||||
for(uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; i++)
|
||||
{
|
||||
if(vs_Input.ViewPosition.z < u_CascadeSplits[i])
|
||||
CascadeIndex = i + 1;
|
||||
}
|
||||
|
||||
float shadowDistance = u_MaxShadowDistance;//u_CascadeSplits[3];
|
||||
float transitionDistance = u_ShadowFade;
|
||||
float distance = length(vs_Input.ViewPosition);
|
||||
ShadowFade = distance - (shadowDistance - transitionDistance);
|
||||
ShadowFade /= transitionDistance;
|
||||
ShadowFade = clamp(1.0 - ShadowFade, 0.0, 1.0);
|
||||
|
||||
bool fadeCascades = u_CascadeFading;
|
||||
float shadowAmount = 1.0;
|
||||
if (fadeCascades)
|
||||
{
|
||||
float cascadeTransitionFade = u_CascadeTransitionFade;
|
||||
|
||||
float c0 = smoothstep(u_CascadeSplits[0] + cascadeTransitionFade * 0.5f, u_CascadeSplits[0] - cascadeTransitionFade * 0.5f, vs_Input.ViewPosition.z);
|
||||
float c1 = smoothstep(u_CascadeSplits[1] + cascadeTransitionFade * 0.5f, u_CascadeSplits[1] - cascadeTransitionFade * 0.5f, vs_Input.ViewPosition.z);
|
||||
float c2 = smoothstep(u_CascadeSplits[2] + cascadeTransitionFade * 0.5f, u_CascadeSplits[2] - cascadeTransitionFade * 0.5f, vs_Input.ViewPosition.z);
|
||||
if (c0 > 0.0 && c0 < 1.0)
|
||||
{
|
||||
// Sample 0 & 1
|
||||
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[0].xyz / vs_Input.ShadowMapCoords[0].w);
|
||||
float shadowAmount0 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[0], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[0], shadowMapCoords);
|
||||
shadowMapCoords = (vs_Input.ShadowMapCoords[1].xyz / vs_Input.ShadowMapCoords[1].w);
|
||||
float shadowAmount1 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords);
|
||||
|
||||
shadowAmount = mix(shadowAmount0, shadowAmount1, c0);
|
||||
}
|
||||
else if (c1 > 0.0 && c1 < 1.0)
|
||||
{
|
||||
// Sample 1 & 2
|
||||
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[1].xyz / vs_Input.ShadowMapCoords[1].w);
|
||||
float shadowAmount1 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords);
|
||||
shadowMapCoords = (vs_Input.ShadowMapCoords[2].xyz / vs_Input.ShadowMapCoords[2].w);
|
||||
float shadowAmount2 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords);
|
||||
|
||||
shadowAmount = mix(shadowAmount1, shadowAmount2, c1);
|
||||
}
|
||||
else if (c2 > 0.0 && c2 < 1.0)
|
||||
{
|
||||
// Sample 2 & 3
|
||||
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[2].xyz / vs_Input.ShadowMapCoords[2].w);
|
||||
float shadowAmount2 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords);
|
||||
shadowMapCoords = (vs_Input.ShadowMapCoords[3].xyz / vs_Input.ShadowMapCoords[3].w);
|
||||
float shadowAmount3 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[3], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[3], shadowMapCoords);
|
||||
|
||||
shadowAmount = mix(shadowAmount2, shadowAmount3, c2);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[CascadeIndex].xyz / vs_Input.ShadowMapCoords[CascadeIndex].w);
|
||||
shadowAmount = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[CascadeIndex].xyz / vs_Input.ShadowMapCoords[CascadeIndex].w);
|
||||
shadowAmount = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords);
|
||||
}
|
||||
|
||||
float NdotL = dot(m_Params.Normal, u_DirectionalLights.Direction);
|
||||
NdotL = smoothstep(0.0, 0.4, NdotL + 0.2);
|
||||
shadowAmount *= (NdotL * 1.0);
|
||||
|
||||
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
|
||||
vec3 lightContribution = u_DirectionalLights.Multiplier > 0.0f ? (Lighting(F0) * shadowAmount) : vec3(0.0f);
|
||||
|
||||
color = vec4(lightContribution + iblContribution, 1.0);
|
||||
|
||||
// Bloom
|
||||
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||
o_BloomColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
if (brightness > u_BloomThreshold)
|
||||
o_BloomColor = color;
|
||||
|
||||
if (u_ShowCascades)
|
||||
{
|
||||
switch(CascadeIndex)
|
||||
{
|
||||
case 0:
|
||||
color.rgb *= vec3(1.0f, 0.25f, 0.25f);
|
||||
break;
|
||||
case 1:
|
||||
color.rgb *= vec3(0.25f, 1.0f, 0.25f);
|
||||
break;
|
||||
case 2:
|
||||
color.rgb *= vec3(0.25f, 0.25f, 1.0f);
|
||||
break;
|
||||
case 3:
|
||||
color.rgb *= vec3(1.0f, 1.0f, 0.25f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
// -----------------------------
|
||||
// -- From Hazel Engine PBR shader --
|
||||
// -- Hazel Engine PBR shader --
|
||||
// -----------------------------
|
||||
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
||||
// Currently heavily updated.
|
||||
// Currently heavily updated.
|
||||
//
|
||||
// References upon which this is based:
|
||||
// - Unreal Engine 4 PBR notes (https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf)
|
||||
@ -19,27 +19,41 @@ layout(location = 3) in vec3 a_Binormal;
|
||||
layout(location = 4) in vec2 a_TexCoord;
|
||||
|
||||
uniform mat4 u_ViewProjectionMatrix;
|
||||
uniform mat4 u_ViewMatrix;
|
||||
uniform mat4 u_Transform;
|
||||
|
||||
uniform mat4 u_LightMatrixCascade0;
|
||||
uniform mat4 u_LightMatrixCascade1;
|
||||
uniform mat4 u_LightMatrixCascade2;
|
||||
uniform mat4 u_LightMatrixCascade3;
|
||||
|
||||
out VertexOutput
|
||||
{
|
||||
vec3 WorldPosition;
|
||||
vec3 Normal;
|
||||
vec3 Normal;
|
||||
vec2 TexCoord;
|
||||
mat3 WorldNormals;
|
||||
mat3 WorldTransform;
|
||||
vec3 Binormal;
|
||||
vec4 ShadowMapCoords[4];
|
||||
vec3 ViewPosition;
|
||||
} vs_Output;
|
||||
|
||||
void main()
|
||||
{
|
||||
vs_Output.WorldPosition = vec3(u_Transform * vec4(a_Position, 1.0));
|
||||
vs_Output.Normal = mat3(u_Transform) * a_Normal;
|
||||
vs_Output.Normal = mat3(u_Transform) * a_Normal;
|
||||
vs_Output.TexCoord = vec2(a_TexCoord.x, 1.0 - a_TexCoord.y);
|
||||
vs_Output.WorldNormals = mat3(u_Transform) * mat3(a_Tangent, a_Binormal, a_Normal);
|
||||
vs_Output.WorldTransform = mat3(u_Transform);
|
||||
vs_Output.Binormal = a_Binormal;
|
||||
|
||||
vs_Output.ShadowMapCoords[0] = u_LightMatrixCascade0 * vec4(vs_Output.WorldPosition, 1.0);
|
||||
vs_Output.ShadowMapCoords[1] = u_LightMatrixCascade1 * vec4(vs_Output.WorldPosition, 1.0);
|
||||
vs_Output.ShadowMapCoords[2] = u_LightMatrixCascade2 * vec4(vs_Output.WorldPosition, 1.0);
|
||||
vs_Output.ShadowMapCoords[3] = u_LightMatrixCascade3 * vec4(vs_Output.WorldPosition, 1.0);
|
||||
vs_Output.ViewPosition = vec3(u_ViewMatrix * vec4(vs_Output.WorldPosition, 1.0));
|
||||
|
||||
gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0);
|
||||
}
|
||||
|
||||
@ -54,7 +68,8 @@ const int LightCount = 1;
|
||||
// Constant normal incidence Fresnel factor for all dielectrics.
|
||||
const vec3 Fdielectric = vec3(0.04);
|
||||
|
||||
struct Light {
|
||||
struct DirectionalLight
|
||||
{
|
||||
vec3 Direction;
|
||||
vec3 Radiance;
|
||||
float Multiplier;
|
||||
@ -63,16 +78,19 @@ struct Light {
|
||||
in VertexOutput
|
||||
{
|
||||
vec3 WorldPosition;
|
||||
vec3 Normal;
|
||||
vec3 Normal;
|
||||
vec2 TexCoord;
|
||||
mat3 WorldNormals;
|
||||
mat3 WorldTransform;
|
||||
vec3 Binormal;
|
||||
vec4 ShadowMapCoords[4];
|
||||
vec3 ViewPosition;
|
||||
} vs_Input;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(location = 1) out vec4 o_BloomColor;
|
||||
|
||||
uniform Light lights;
|
||||
uniform DirectionalLight u_DirectionalLights;
|
||||
uniform vec3 u_CameraPosition;
|
||||
|
||||
// PBR texture inputs
|
||||
@ -88,6 +106,25 @@ uniform samplerCube u_EnvIrradianceTex;
|
||||
// BRDF LUT
|
||||
uniform sampler2D u_BRDFLUTTexture;
|
||||
|
||||
// PCSS
|
||||
uniform sampler2D u_ShadowMapTexture[4];
|
||||
uniform mat4 u_LightView;
|
||||
uniform bool u_ShowCascades;
|
||||
uniform bool u_SoftShadows;
|
||||
uniform float u_LightSize;
|
||||
uniform float u_MaxShadowDistance;
|
||||
uniform float u_ShadowFade;
|
||||
uniform bool u_CascadeFading;
|
||||
uniform float u_CascadeTransitionFade;
|
||||
|
||||
uniform vec4 u_CascadeSplits;
|
||||
|
||||
uniform float u_IBLContribution;
|
||||
|
||||
uniform float u_BloomThreshold;
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
uniform vec3 u_AlbedoColor;
|
||||
uniform float u_Metalness;
|
||||
uniform float u_Roughness;
|
||||
@ -95,7 +132,6 @@ uniform float u_Roughness;
|
||||
uniform float u_EnvMapRotation;
|
||||
|
||||
// Toggles
|
||||
uniform float u_RadiancePrefilter;
|
||||
uniform float u_AlbedoTexToggle;
|
||||
uniform float u_NormalTexToggle;
|
||||
uniform float u_MetalnessTexToggle;
|
||||
@ -141,23 +177,23 @@ float gaSchlickGGX(float cosLi, float NdotV, float roughness)
|
||||
|
||||
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||
{
|
||||
float r = (roughness + 1.0);
|
||||
float k = (r*r) / 8.0;
|
||||
float r = (roughness + 1.0);
|
||||
float k = (r*r) / 8.0;
|
||||
|
||||
float nom = NdotV;
|
||||
float denom = NdotV * (1.0 - k) + k;
|
||||
float nom = NdotV;
|
||||
float denom = NdotV * (1.0 - k) + k;
|
||||
|
||||
return nom / denom;
|
||||
return nom / denom;
|
||||
}
|
||||
|
||||
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||
{
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||
|
||||
return ggx1 * ggx2;
|
||||
return ggx1 * ggx2;
|
||||
}
|
||||
|
||||
// Shlick's approximation of the Fresnel factor.
|
||||
@ -168,26 +204,26 @@ vec3 fresnelSchlick(vec3 F0, float cosTheta)
|
||||
|
||||
vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
|
||||
{
|
||||
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
||||
}
|
||||
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------
|
||||
// The following code (from Unreal Engine 4's paper) shows how to filter the environment map
|
||||
// for different roughnesses. This is mean to be computed offline and stored in cube map mips,
|
||||
// so turning this on online will cause poor performance
|
||||
float RadicalInverse_VdC(uint bits)
|
||||
float RadicalInverse_VdC(uint bits)
|
||||
{
|
||||
bits = (bits << 16u) | (bits >> 16u);
|
||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||
bits = (bits << 16u) | (bits >> 16u);
|
||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||
}
|
||||
|
||||
vec2 Hammersley(uint i, uint N)
|
||||
{
|
||||
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
|
||||
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
|
||||
}
|
||||
|
||||
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N)
|
||||
@ -234,11 +270,11 @@ vec3 PrefilterEnvMap(float Roughness, vec3 R)
|
||||
|
||||
vec3 RotateVectorAboutY(float angle, vec3 vec)
|
||||
{
|
||||
angle = radians(angle);
|
||||
mat3x3 rotationMatrix ={vec3(cos(angle),0.0,sin(angle)),
|
||||
vec3(0.0,1.0,0.0),
|
||||
vec3(-sin(angle),0.0,cos(angle))};
|
||||
return rotationMatrix * vec;
|
||||
angle = radians(angle);
|
||||
mat3x3 rotationMatrix ={vec3(cos(angle),0.0,sin(angle)),
|
||||
vec3(0.0,1.0,0.0),
|
||||
vec3(-sin(angle),0.0,cos(angle))};
|
||||
return rotationMatrix * vec;
|
||||
}
|
||||
|
||||
vec3 Lighting(vec3 F0)
|
||||
@ -246,8 +282,8 @@ vec3 Lighting(vec3 F0)
|
||||
vec3 result = vec3(0.0);
|
||||
for(int i = 0; i < LightCount; i++)
|
||||
{
|
||||
vec3 Li = -lights.Direction;
|
||||
vec3 Lradiance = lights.Radiance * lights.Multiplier;
|
||||
vec3 Li = u_DirectionalLights.Direction;
|
||||
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Multiplier;
|
||||
vec3 Lh = normalize(Li + m_Params.View);
|
||||
|
||||
// Calculate angles between surface normal and various light vectors.
|
||||
@ -273,7 +309,6 @@ vec3 IBL(vec3 F0, vec3 Lr)
|
||||
{
|
||||
vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
|
||||
vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness);
|
||||
// vec3 F = fresnelSchlickR(F0, m_Params.NdotV);
|
||||
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
||||
vec3 diffuseIBL = m_Params.Albedo * irradiance;
|
||||
|
||||
@ -289,13 +324,188 @@ vec3 IBL(vec3 F0, vec3 Lr)
|
||||
return kd * diffuseIBL + specularIBL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// PCSS
|
||||
/////////////////////////////////////////////
|
||||
|
||||
uint CascadeIndex = 0;
|
||||
float ShadowFade = 1.0;
|
||||
|
||||
float GetShadowBias()
|
||||
{
|
||||
const float MINIMUM_SHADOW_BIAS = 0.002;
|
||||
float bias = max(MINIMUM_SHADOW_BIAS * (1.0 - dot(m_Params.Normal, u_DirectionalLights.Direction)), MINIMUM_SHADOW_BIAS);
|
||||
return bias;
|
||||
}
|
||||
|
||||
float HardShadows_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords)
|
||||
{
|
||||
float bias = GetShadowBias();
|
||||
float z = texture(shadowMap, shadowCoords.xy).x;
|
||||
return 1.0 - step(z + bias, shadowCoords.z) * ShadowFade;
|
||||
}
|
||||
|
||||
// Penumbra
|
||||
|
||||
// this search area estimation comes from the following article:
|
||||
// http://developer.download.nvidia.com/whitepapers/2008/PCSS_DirectionalLight_Integration.pdf
|
||||
float SearchWidth(float uvLightSize, float receiverDistance)
|
||||
{
|
||||
const float NEAR = 0.1;
|
||||
return uvLightSize * (receiverDistance - NEAR) / u_CameraPosition.z;
|
||||
}
|
||||
|
||||
float u_light_zNear = 0.0; // 0.01 gives artifacts? maybe because of ortho proj?
|
||||
float u_light_zFar = 10000.0;
|
||||
vec2 u_lightRadiusUV = vec2(0.05);
|
||||
|
||||
vec2 searchRegionRadiusUV(float zWorld)
|
||||
{
|
||||
return u_lightRadiusUV * (zWorld - u_light_zNear) / zWorld;
|
||||
}
|
||||
|
||||
const vec2 PoissonDistribution[64] = vec2[](
|
||||
vec2(-0.884081, 0.124488),
|
||||
vec2(-0.714377, 0.027940),
|
||||
vec2(-0.747945, 0.227922),
|
||||
vec2(-0.939609, 0.243634),
|
||||
vec2(-0.985465, 0.045534),
|
||||
vec2(-0.861367, -0.136222),
|
||||
vec2(-0.881934, 0.396908),
|
||||
vec2(-0.466938, 0.014526),
|
||||
vec2(-0.558207, 0.212662),
|
||||
vec2(-0.578447, -0.095822),
|
||||
vec2(-0.740266, -0.095631),
|
||||
vec2(-0.751681, 0.472604),
|
||||
vec2(-0.553147, -0.243177),
|
||||
vec2(-0.674762, -0.330730),
|
||||
vec2(-0.402765, -0.122087),
|
||||
vec2(-0.319776, -0.312166),
|
||||
vec2(-0.413923, -0.439757),
|
||||
vec2(-0.979153, -0.201245),
|
||||
vec2(-0.865579, -0.288695),
|
||||
vec2(-0.243704, -0.186378),
|
||||
vec2(-0.294920, -0.055748),
|
||||
vec2(-0.604452, -0.544251),
|
||||
vec2(-0.418056, -0.587679),
|
||||
vec2(-0.549156, -0.415877),
|
||||
vec2(-0.238080, -0.611761),
|
||||
vec2(-0.267004, -0.459702),
|
||||
vec2(-0.100006, -0.229116),
|
||||
vec2(-0.101928, -0.380382),
|
||||
vec2(-0.681467, -0.700773),
|
||||
vec2(-0.763488, -0.543386),
|
||||
vec2(-0.549030, -0.750749),
|
||||
vec2(-0.809045, -0.408738),
|
||||
vec2(-0.388134, -0.773448),
|
||||
vec2(-0.429392, -0.894892),
|
||||
vec2(-0.131597, 0.065058),
|
||||
vec2(-0.275002, 0.102922),
|
||||
vec2(-0.106117, -0.068327),
|
||||
vec2(-0.294586, -0.891515),
|
||||
vec2(-0.629418, 0.379387),
|
||||
vec2(-0.407257, 0.339748),
|
||||
vec2(0.071650, -0.384284),
|
||||
vec2(0.022018, -0.263793),
|
||||
vec2(0.003879, -0.136073),
|
||||
vec2(-0.137533, -0.767844),
|
||||
vec2(-0.050874, -0.906068),
|
||||
vec2(0.114133, -0.070053),
|
||||
vec2(0.163314, -0.217231),
|
||||
vec2(-0.100262, -0.587992),
|
||||
vec2(-0.004942, 0.125368),
|
||||
vec2(0.035302, -0.619310),
|
||||
vec2(0.195646, -0.459022),
|
||||
vec2(0.303969, -0.346362),
|
||||
vec2(-0.678118, 0.685099),
|
||||
vec2(-0.628418, 0.507978),
|
||||
vec2(-0.508473, 0.458753),
|
||||
vec2(0.032134, -0.782030),
|
||||
vec2(0.122595, 0.280353),
|
||||
vec2(-0.043643, 0.312119),
|
||||
vec2(0.132993, 0.085170),
|
||||
vec2(-0.192106, 0.285848),
|
||||
vec2(0.183621, -0.713242),
|
||||
vec2(0.265220, -0.596716),
|
||||
vec2(-0.009628, -0.483058),
|
||||
vec2(-0.018516, 0.435703)
|
||||
);
|
||||
|
||||
vec2 SamplePoisson(int index)
|
||||
{
|
||||
return PoissonDistribution[index % 64];
|
||||
}
|
||||
|
||||
float FindBlockerDistance_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords, float uvLightSize)
|
||||
{
|
||||
float bias = GetShadowBias();
|
||||
|
||||
int numBlockerSearchSamples = 64;
|
||||
int blockers = 0;
|
||||
float avgBlockerDistance = 0;
|
||||
|
||||
float zEye = -(u_LightView * vec4(vs_Input.WorldPosition, 1.0)).z;
|
||||
vec2 searchWidth = searchRegionRadiusUV(zEye);
|
||||
for (int i = 0; i < numBlockerSearchSamples; i++)
|
||||
{
|
||||
float z = texture(shadowMap, shadowCoords.xy + SamplePoisson(i) * searchWidth).r;
|
||||
if (z < (shadowCoords.z - bias))
|
||||
{
|
||||
blockers++;
|
||||
avgBlockerDistance += z;
|
||||
}
|
||||
}
|
||||
|
||||
if (blockers > 0)
|
||||
return avgBlockerDistance / float(blockers);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
float PenumbraWidth(sampler2D shadowMap, vec3 shadowCoords, float uvLightSize)
|
||||
{
|
||||
float blockerDistance = FindBlockerDistance_DirectionalLight(shadowMap, shadowCoords, uvLightSize);
|
||||
if (blockerDistance == -1)
|
||||
return -1;
|
||||
|
||||
return (shadowCoords.z - blockerDistance) / blockerDistance;
|
||||
}
|
||||
|
||||
float PCF_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords, float uvRadius)
|
||||
{
|
||||
float bias = GetShadowBias();
|
||||
int numPCFSamples = 64;
|
||||
float sum = 0;
|
||||
for (int i = 0; i < numPCFSamples; i++)
|
||||
{
|
||||
float z = texture(shadowMap, shadowCoords.xy + SamplePoisson(i) * uvRadius).r;
|
||||
sum += (z < (shadowCoords.z - bias)) ? 1 : 0;
|
||||
}
|
||||
return sum / numPCFSamples;
|
||||
}
|
||||
|
||||
float PCSS_DirectionalLight(sampler2D shadowMap, vec3 shadowCoords, float uvLightSize)
|
||||
{
|
||||
float blockerDistance = FindBlockerDistance_DirectionalLight(shadowMap, shadowCoords, uvLightSize);
|
||||
if (blockerDistance == -1)
|
||||
return 1;
|
||||
|
||||
float penumbraWidth = (shadowCoords.z - blockerDistance) / blockerDistance;
|
||||
|
||||
float NEAR = 0.01; // Should this value be tweakable?
|
||||
float uvRadius = penumbraWidth * uvLightSize * NEAR / shadowCoords.z;
|
||||
return 1.0 - PCF_DirectionalLight(shadowMap, shadowCoords, uvRadius) * ShadowFade;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
||||
void main()
|
||||
{
|
||||
// Standard PBR inputs
|
||||
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
|
||||
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
|
||||
m_Params.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness;
|
||||
m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
|
||||
m_Params.Roughness = max(m_Params.Roughness, 0.05); // Minimum roughness of 0.05 to keep specular highlight
|
||||
m_Params.Roughness = max(m_Params.Roughness, 0.05); // Minimum roughness of 0.05 to keep specular highlight
|
||||
|
||||
// Normals (either from vertex or map)
|
||||
m_Params.Normal = normalize(vs_Input.Normal);
|
||||
@ -307,16 +517,109 @@ void main()
|
||||
|
||||
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
|
||||
m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0);
|
||||
|
||||
|
||||
// Specular reflection vector
|
||||
vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View;
|
||||
|
||||
// Fresnel reflectance, metals use albedo
|
||||
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
|
||||
|
||||
vec3 lightContribution = Lighting(F0);
|
||||
vec3 iblContribution = IBL(F0, Lr);
|
||||
const uint SHADOW_MAP_CASCADE_COUNT = 4;
|
||||
for(uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; i++)
|
||||
{
|
||||
if(vs_Input.ViewPosition.z < u_CascadeSplits[i])
|
||||
CascadeIndex = i + 1;
|
||||
}
|
||||
|
||||
float shadowDistance = u_MaxShadowDistance;//u_CascadeSplits[3];
|
||||
float transitionDistance = u_ShadowFade;
|
||||
float distance = length(vs_Input.ViewPosition);
|
||||
ShadowFade = distance - (shadowDistance - transitionDistance);
|
||||
ShadowFade /= transitionDistance;
|
||||
ShadowFade = clamp(1.0 - ShadowFade, 0.0, 1.0);
|
||||
|
||||
bool fadeCascades = u_CascadeFading;
|
||||
float shadowAmount = 1.0;
|
||||
if (fadeCascades)
|
||||
{
|
||||
float cascadeTransitionFade = u_CascadeTransitionFade;
|
||||
|
||||
float c0 = smoothstep(u_CascadeSplits[0] + cascadeTransitionFade * 0.5f, u_CascadeSplits[0] - cascadeTransitionFade * 0.5f, vs_Input.ViewPosition.z);
|
||||
float c1 = smoothstep(u_CascadeSplits[1] + cascadeTransitionFade * 0.5f, u_CascadeSplits[1] - cascadeTransitionFade * 0.5f, vs_Input.ViewPosition.z);
|
||||
float c2 = smoothstep(u_CascadeSplits[2] + cascadeTransitionFade * 0.5f, u_CascadeSplits[2] - cascadeTransitionFade * 0.5f, vs_Input.ViewPosition.z);
|
||||
if (c0 > 0.0 && c0 < 1.0)
|
||||
{
|
||||
// Sample 0 & 1
|
||||
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[0].xyz / vs_Input.ShadowMapCoords[0].w);
|
||||
float shadowAmount0 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[0], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[0], shadowMapCoords);
|
||||
shadowMapCoords = (vs_Input.ShadowMapCoords[1].xyz / vs_Input.ShadowMapCoords[1].w);
|
||||
float shadowAmount1 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords);
|
||||
|
||||
shadowAmount = mix(shadowAmount0, shadowAmount1, c0);
|
||||
}
|
||||
else if (c1 > 0.0 && c1 < 1.0)
|
||||
{
|
||||
// Sample 1 & 2
|
||||
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[1].xyz / vs_Input.ShadowMapCoords[1].w);
|
||||
float shadowAmount1 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[1], shadowMapCoords);
|
||||
shadowMapCoords = (vs_Input.ShadowMapCoords[2].xyz / vs_Input.ShadowMapCoords[2].w);
|
||||
float shadowAmount2 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords);
|
||||
|
||||
shadowAmount = mix(shadowAmount1, shadowAmount2, c1);
|
||||
}
|
||||
else if (c2 > 0.0 && c2 < 1.0)
|
||||
{
|
||||
// Sample 2 & 3
|
||||
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[2].xyz / vs_Input.ShadowMapCoords[2].w);
|
||||
float shadowAmount2 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[2], shadowMapCoords);
|
||||
shadowMapCoords = (vs_Input.ShadowMapCoords[3].xyz / vs_Input.ShadowMapCoords[3].w);
|
||||
float shadowAmount3 = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[3], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[3], shadowMapCoords);
|
||||
|
||||
shadowAmount = mix(shadowAmount2, shadowAmount3, c2);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[CascadeIndex].xyz / vs_Input.ShadowMapCoords[CascadeIndex].w);
|
||||
shadowAmount = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vec3 shadowMapCoords = (vs_Input.ShadowMapCoords[CascadeIndex].xyz / vs_Input.ShadowMapCoords[CascadeIndex].w);
|
||||
shadowAmount = u_SoftShadows ? PCSS_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords, u_LightSize) : HardShadows_DirectionalLight(u_ShadowMapTexture[CascadeIndex], shadowMapCoords);
|
||||
}
|
||||
|
||||
float NdotL = dot(m_Params.Normal, u_DirectionalLights.Direction);
|
||||
NdotL = smoothstep(0.0, 0.4, NdotL + 0.2);
|
||||
shadowAmount *= (NdotL * 1.0);
|
||||
|
||||
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
|
||||
vec3 lightContribution = u_DirectionalLights.Multiplier > 0.0f ? (Lighting(F0) * shadowAmount) : vec3(0.0f);
|
||||
|
||||
color = vec4(lightContribution + iblContribution, 1.0);
|
||||
// color = vec4(iblContribution, 1.0);
|
||||
|
||||
// Bloom
|
||||
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||
o_BloomColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
if (brightness > u_BloomThreshold)
|
||||
o_BloomColor = color;
|
||||
|
||||
if (u_ShowCascades)
|
||||
{
|
||||
switch(CascadeIndex)
|
||||
{
|
||||
case 0:
|
||||
color.rgb *= vec3(1.0f, 0.25f, 0.25f);
|
||||
break;
|
||||
case 1:
|
||||
color.rgb *= vec3(0.25f, 1.0f, 0.25f);
|
||||
break;
|
||||
case 2:
|
||||
color.rgb *= vec3(0.25f, 0.25f, 1.0f);
|
||||
break;
|
||||
case 3:
|
||||
color.rgb *= vec3(1.0f, 1.0f, 0.25f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,20 +17,34 @@ void main()
|
||||
#version 430
|
||||
|
||||
layout(location = 0) out vec4 o_Color;
|
||||
layout(location = 1) out vec4 o_BloomTexture;
|
||||
|
||||
in vec2 v_TexCoord;
|
||||
|
||||
uniform sampler2DMS u_Texture;
|
||||
|
||||
uniform float u_Exposure;
|
||||
uniform int u_TextureSamples;
|
||||
|
||||
vec4 MultiSampleTexture(sampler2DMS tex, ivec2 texCoord, int samples)
|
||||
uniform bool u_EnableBloom;
|
||||
uniform float u_BloomThreshold;
|
||||
|
||||
const float uFar = 1.0;
|
||||
|
||||
vec4 SampleTexture(sampler2D tex, vec2 texCoord)
|
||||
{
|
||||
return texture(tex, texCoord);
|
||||
}
|
||||
|
||||
vec4 MultiSampleTexture(sampler2DMS tex, vec2 tc)
|
||||
{
|
||||
ivec2 texSize = textureSize(tex);
|
||||
ivec2 texCoord = ivec2(tc * texSize);
|
||||
vec4 result = vec4(0.0);
|
||||
for (int i = 0; i < samples; i++)
|
||||
for (int i = 0; i < u_TextureSamples; i++)
|
||||
result += texelFetch(tex, texCoord, i);
|
||||
|
||||
result /= float(samples);
|
||||
result /= float(u_TextureSamples);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -39,10 +53,18 @@ void main()
|
||||
const float gamma = 2.2;
|
||||
const float pureWhite = 1.0;
|
||||
|
||||
ivec2 texSize = textureSize(u_Texture);
|
||||
ivec2 texCoord = ivec2(v_TexCoord * texSize);
|
||||
vec4 msColor = MultiSampleTexture(u_Texture, texCoord, u_TextureSamples);
|
||||
vec3 color = msColor.rgb * u_Exposure;//texture(u_Texture, v_TexCoord).rgb * u_Exposure;
|
||||
// Tonemapping
|
||||
vec4 msColor = MultiSampleTexture(u_Texture, v_TexCoord);
|
||||
|
||||
vec3 color = msColor.rgb;
|
||||
|
||||
if (u_EnableBloom)
|
||||
{
|
||||
vec3 bloomColor = MultiSampleTexture(u_Texture, v_TexCoord).rgb;
|
||||
color += bloomColor;
|
||||
}
|
||||
|
||||
color *= u_Exposure;
|
||||
|
||||
// Reinhard tonemapping operator.
|
||||
// see: "Photographic Tone Reproduction for Digital Images", eq. 4
|
||||
@ -54,4 +76,8 @@ void main()
|
||||
|
||||
// Gamma correction.
|
||||
o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0);
|
||||
}
|
||||
|
||||
// Show over-exposed areas
|
||||
// if (o_Color.r > 1.0 || o_Color.g > 1.0 || o_Color.b > 1.0)
|
||||
// o_Color.rgb *= vec3(1.0, 0.25, 0.25);
|
||||
}
|
||||
|
||||
23
Editor/assets/shaders/ShadowMap.glsl
Normal file
23
Editor/assets/shaders/ShadowMap.glsl
Normal file
@ -0,0 +1,23 @@
|
||||
// Shadow Map shader
|
||||
|
||||
#type vertex
|
||||
#version 430
|
||||
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
|
||||
uniform mat4 u_ViewProjection;
|
||||
uniform mat4 u_Transform;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
|
||||
}
|
||||
|
||||
#type fragment
|
||||
#version 430
|
||||
|
||||
layout(location = 0) out vec4 o_Color;
|
||||
|
||||
void main()
|
||||
{
|
||||
}
|
||||
35
Editor/assets/shaders/ShadowMap_Anim.glsl
Normal file
35
Editor/assets/shaders/ShadowMap_Anim.glsl
Normal file
@ -0,0 +1,35 @@
|
||||
// Shadow Map shader
|
||||
|
||||
#type vertex
|
||||
#version 430
|
||||
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
|
||||
layout(location = 5) in ivec4 a_BoneIndices;
|
||||
layout(location = 6) in vec4 a_BoneWeights;
|
||||
|
||||
uniform mat4 u_ViewProjection;
|
||||
uniform mat4 u_Transform;
|
||||
|
||||
const int MAX_BONES = 100;
|
||||
uniform mat4 u_BoneTransforms[100];
|
||||
|
||||
void main()
|
||||
{
|
||||
mat4 boneTransform = u_BoneTransforms[a_BoneIndices[0]] * a_BoneWeights[0];
|
||||
boneTransform += u_BoneTransforms[a_BoneIndices[1]] * a_BoneWeights[1];
|
||||
boneTransform += u_BoneTransforms[a_BoneIndices[2]] * a_BoneWeights[2];
|
||||
boneTransform += u_BoneTransforms[a_BoneIndices[3]] * a_BoneWeights[3];
|
||||
|
||||
vec4 localPosition = boneTransform * vec4(a_Position, 1.0);
|
||||
gl_Position = u_ViewProjection * u_Transform * localPosition;
|
||||
}
|
||||
|
||||
#type fragment
|
||||
#version 430
|
||||
|
||||
layout(location = 0) out vec4 o_Color;
|
||||
|
||||
void main()
|
||||
{
|
||||
}
|
||||
@ -24,10 +24,13 @@ layout(location = 0) out vec4 finalColor;
|
||||
|
||||
uniform samplerCube u_Texture;
|
||||
uniform float u_TextureLod;
|
||||
uniform float u_SkyIntensity;
|
||||
|
||||
in vec3 v_Position;
|
||||
|
||||
void main()
|
||||
{
|
||||
finalColor = textureLod(u_Texture, v_Position, u_TextureLod);
|
||||
vec3 color = textureLod(u_Texture, v_Position, u_TextureLod).rgb * u_SkyIntensity;
|
||||
finalColor = vec4(color, 1.0);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user