VisualShader work
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
e204f7ac55
commit
46fc63bc63
@ -1,72 +1,8 @@
|
||||
#version 450 core
|
||||
#extension GL_ARB_shading_language_include : require
|
||||
#include "./lib/lights.fs"
|
||||
|
||||
//FragmentShader.fs
|
||||
|
||||
/**
|
||||
Maximum number of point lights
|
||||
*/
|
||||
#define MAX_POINT_LIGHTS 512
|
||||
|
||||
/**
|
||||
Maximum number of lights per cluster
|
||||
*/
|
||||
#define MAX_LIGHTS_PER_CLUSTER 100
|
||||
|
||||
/**
|
||||
Bind points for different SSBOs
|
||||
*/
|
||||
#define CLUSTER_SSBO_BIND_POINT 1
|
||||
#define POINT_LIGHT_SSBO_BIND_POINT 2
|
||||
#define DIRECT_LIGHT_SSBO_BIND_POINT 3
|
||||
|
||||
/**
|
||||
The direct global light
|
||||
*/
|
||||
struct DirectLight {
|
||||
vec3 direction;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
/**
|
||||
A point light
|
||||
*/
|
||||
struct PointLight {
|
||||
vec4 position;
|
||||
vec4 color;
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
float radius;
|
||||
};
|
||||
|
||||
/**
|
||||
A light cluster
|
||||
*/
|
||||
struct Cluster {
|
||||
vec4 minPoint;
|
||||
vec4 maxPoint;
|
||||
uint count;
|
||||
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
|
||||
};
|
||||
|
||||
/**
|
||||
Cutoff for fragment alpha
|
||||
*/
|
||||
#define FRAGMENT_ALPHA_CUTOFF 0.001
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
//Shaders/FragmentShader.fs
|
||||
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
@ -82,33 +18,12 @@ in vec4 FragPosLightSpace;
|
||||
|
||||
|
||||
uniform vec3 viewPos;
|
||||
// uniform DirLight dirLight;
|
||||
// uniform PointLight pointLights[NR_POINT_LIGHTS];
|
||||
// uniform SpotLight spotLight;
|
||||
uniform Material material;
|
||||
|
||||
//texture stuff
|
||||
// uniform sampler2D ourTexture;
|
||||
uniform int hasTransparency;
|
||||
// uniform sampler2D specularTexture;
|
||||
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
The output
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
|
||||
|
||||
// function prototypes
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
out vec4 FragColor;
|
||||
|
||||
void main(){
|
||||
if(texture(material.diffuse, TexCoord).a < FRAGMENT_ALPHA_CUTOFF){
|
||||
@ -148,121 +63,3 @@ void main(){
|
||||
//this final calculation is for transparency
|
||||
FragColor = vec4(finalColor, texture(material.diffuse, TexCoord).a);//texture(ourTexture, TexCoord);//vec4(result, 1.0);
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityAmbient(){
|
||||
//calculate average of ambient light
|
||||
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityTotal(vec3 normal){
|
||||
//ambient intensity
|
||||
float ambientLightIntensity = calcLightIntensityAmbient();
|
||||
|
||||
//get direct intensity
|
||||
float directLightIntensity = calcLightIntensityDir(normal);
|
||||
|
||||
//sum
|
||||
float total = ambientLightIntensity + directLightIntensity;
|
||||
return total;
|
||||
}
|
||||
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = diffuse * attenuation;
|
||||
// specular *= attenuation;
|
||||
vec3 specular = vec3(0,0,0);
|
||||
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the light cluster this fragment belongs to
|
||||
*/
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
|
||||
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
|
||||
vec2 tileSize = screenDimensions / gridSize.xy;
|
||||
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
|
||||
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
|
||||
}
|
||||
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||
|
||||
// perform perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
//transform to NDC
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
//get closest depth from light's POV
|
||||
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
//get depth of current fragment
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
//calculate bias
|
||||
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||
|
||||
//calculate shadow value
|
||||
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||
|
||||
if(projCoords.z > 1.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
//calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping
|
||||
//ie the fragment is already facing away from the light source
|
||||
float dotprod = dot(normalize(lightDir),normalize(normal));
|
||||
|
||||
if(dotprod > 0.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
// shadow = currentDepth;
|
||||
|
||||
return clamp(1.0 - shadow, 0.0, 0.7);
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
//Vertex Shader
|
||||
#version 330 core
|
||||
#version 450 core
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//Vertex Shader
|
||||
#version 330 core
|
||||
#version 450 core
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,38 +1,10 @@
|
||||
#version 330 core
|
||||
#version 450 core
|
||||
#extension GL_ARB_shading_language_include : require
|
||||
#include "../../lib/lights.fs"
|
||||
|
||||
//celShading.fs
|
||||
|
||||
#define NR_POINT_LIGHTS 10
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
|
||||
layout (std140) uniform Lights {
|
||||
// this is how many because we have to align
|
||||
// bytes it SHOULD in multiples of 16, this
|
||||
// take it where it ACTUALLY is
|
||||
//
|
||||
//refer: https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL
|
||||
//
|
||||
// base alignment aligned offset
|
||||
//direct light
|
||||
vec3 dLDirection; // 16 0
|
||||
vec3 dLAmbient; // 16 16
|
||||
vec3 dLDiffuse; // 16 32
|
||||
vec3 dLSpecular; // 16 48
|
||||
|
||||
//point light
|
||||
vec3 pLposition[NR_POINT_LIGHTS]; // 16*10 64
|
||||
float pLconstant[NR_POINT_LIGHTS]; // 16*10 224
|
||||
float pLlinear[NR_POINT_LIGHTS]; // 16*10 384
|
||||
float pLquadratic[NR_POINT_LIGHTS]; // 16*10 544
|
||||
vec3 pLambient[NR_POINT_LIGHTS]; // 16*10 704
|
||||
vec3 pLdiffuse[NR_POINT_LIGHTS]; // 16*10 864
|
||||
vec3 pLspecular[NR_POINT_LIGHTS]; // 16*10 1024
|
||||
|
||||
//for a total size of 1184
|
||||
|
||||
};
|
||||
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
@ -52,27 +24,15 @@ uniform vec3 viewPos;
|
||||
// uniform SpotLight spotLight;
|
||||
uniform Material material;
|
||||
|
||||
//texture stuff
|
||||
// uniform sampler2D ourTexture;
|
||||
uniform int hasTransparency;
|
||||
// uniform sampler2D specularTexture;
|
||||
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
|
||||
// function prototypes
|
||||
// vec3 CalcDirLight(vec3 normal, vec3 viewDir);
|
||||
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
// vec3 CalcSpotLight(vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
/**
|
||||
The output
|
||||
*/
|
||||
out vec4 FragColor;
|
||||
|
||||
void main(){
|
||||
if(hasTransparency == 1){
|
||||
if(texture(material.diffuse, TexCoord).a < 0.1){
|
||||
discard;
|
||||
}
|
||||
if(texture(material.diffuse, TexCoord).a < 0.1){
|
||||
discard;
|
||||
}
|
||||
vec3 norm = normalize(Normal);
|
||||
vec3 viewDir = normalize(viewPos - FragPos);
|
||||
@ -84,7 +44,7 @@ void main(){
|
||||
vec3 textureColor = texture(material.diffuse, TexCoord).rgb;
|
||||
|
||||
//shadow
|
||||
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-dLDirection), norm);
|
||||
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), norm);
|
||||
|
||||
//calculate final color
|
||||
vec3 finalColor = textureColor * lightIntensity * max(shadow,0.4);
|
||||
@ -96,155 +56,3 @@ void main(){
|
||||
//this final calculation is for transparency
|
||||
FragColor = vec4(finalColor, texture(material.diffuse, TexCoord).a);//texture(ourTexture, TexCoord);//vec4(result, 1.0);
|
||||
}
|
||||
|
||||
// calculates the color when using a directional light.
|
||||
// vec3 CalcDirLight(vec3 normal, vec3 viewDir){
|
||||
// vec3 lightDir = normalize(-dLDirection);
|
||||
// // diffuse shading
|
||||
// float diff = max(dot(normal, lightDir), 0.0);
|
||||
// // specular shading
|
||||
// // vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// // combine results
|
||||
// vec3 texColor = texture(material.diffuse, TexCoord).rgb;
|
||||
// vec3 diffuse = dLDiffuse * diff;
|
||||
// //vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord).rgb);
|
||||
|
||||
|
||||
// float shadow = ShadowCalculation(FragPosLightSpace, lightDir, normal);
|
||||
|
||||
// return ( dLAmbient + (1.0-shadow) * diffuse ) * texColor;// + specular);
|
||||
// }
|
||||
|
||||
//
|
||||
float calcLightIntensityAmbient(){
|
||||
//calculate average of ambient light
|
||||
float avg = (dLAmbient.x + dLAmbient.y + dLAmbient.z)/3.0;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-dLDirection);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
//clamp for cel shading
|
||||
if(diff > 0.1){
|
||||
diff = 0.3;
|
||||
} else {
|
||||
diff = 0.0;
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityTotal(vec3 normal){
|
||||
//ambient intensity
|
||||
float ambientLightIntensity = calcLightIntensityAmbient();
|
||||
|
||||
//get direct intensity
|
||||
float directLightIntensity = calcLightIntensityDir(normal);
|
||||
|
||||
//sum
|
||||
float total = ambientLightIntensity + directLightIntensity;
|
||||
return total;
|
||||
}
|
||||
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pLposition[i] - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pLposition[i] - fragPos);
|
||||
float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance));
|
||||
// combine results
|
||||
vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient *= attenuation;
|
||||
diffuse *= attenuation;
|
||||
// specular *= attenuation;
|
||||
vec3 specular = vec3(0,0,0);
|
||||
|
||||
vec3 finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
// // calculates the color when using a point light.
|
||||
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
// vec3 lightDir = normalize(pLposition[i] - fragPos);
|
||||
// // diffuse shading
|
||||
// float diff = max(dot(normal, lightDir), 0.0);
|
||||
// // specular shading
|
||||
// // vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// // attenuation
|
||||
// float distance = length(pLposition[i] - fragPos);
|
||||
// float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance));
|
||||
// // combine results
|
||||
// vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// // vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
// ambient *= attenuation;
|
||||
// diffuse *= attenuation;
|
||||
// // specular *= attenuation;
|
||||
// vec3 specular = vec3(0,0,0);
|
||||
|
||||
// vec3 finalValue = (ambient + diffuse + specular);
|
||||
// finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
|
||||
// return finalValue;
|
||||
// }
|
||||
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||
|
||||
// perform perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
//transform to NDC
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
//get closest depth from light's POV
|
||||
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
//get depth of current fragment
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
//calculate bias
|
||||
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||
|
||||
//calculate shadow value
|
||||
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||
|
||||
if(projCoords.z > 1.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
//calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping
|
||||
//ie the fragment is already facing away from the light source
|
||||
float dotprod = dot(normalize(lightDir),normalize(normal));
|
||||
|
||||
if(dotprod > 0.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
// shadow = currentDepth;
|
||||
|
||||
return shadow;
|
||||
}
|
||||
@ -1,69 +1,11 @@
|
||||
#version 450 core
|
||||
|
||||
/**
|
||||
Bind points for different SSBOs
|
||||
*/
|
||||
#define CLUSTER_SSBO_BIND_POINT 1
|
||||
#define POINT_LIGHT_SSBO_BIND_POINT 2
|
||||
#define DIRECT_LIGHT_SSBO_BIND_POINT 3
|
||||
|
||||
|
||||
/**
|
||||
Maximum number of point lights
|
||||
*/
|
||||
#define MAX_POINT_LIGHTS 512
|
||||
|
||||
/**
|
||||
Maximum number of lights per cluster
|
||||
*/
|
||||
#define MAX_LIGHTS_PER_CLUSTER 100
|
||||
|
||||
/**
|
||||
The direct global light
|
||||
*/
|
||||
struct DirectLight {
|
||||
vec3 direction;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
/**
|
||||
A point light
|
||||
*/
|
||||
struct PointLight {
|
||||
vec4 position;
|
||||
vec4 color;
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
float radius;
|
||||
};
|
||||
|
||||
/**
|
||||
A light cluster
|
||||
*/
|
||||
struct Cluster {
|
||||
vec4 minPoint;
|
||||
vec4 maxPoint;
|
||||
uint count;
|
||||
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
|
||||
};
|
||||
#extension GL_ARB_shading_language_include : require
|
||||
#include "../../../lib/lights.fs"
|
||||
|
||||
|
||||
layout (location = 0) out vec4 accum;
|
||||
layout (location = 1) out float reveal;
|
||||
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
sampler2D specular;
|
||||
@ -86,25 +28,10 @@ uniform vec3 viewPos;
|
||||
uniform Material material;
|
||||
|
||||
|
||||
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
uniform mat4 view;
|
||||
|
||||
|
||||
//function prototypes
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
uint findCluster(vec3 FragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
float linearizeDepth(float d,float zNear,float zFar);
|
||||
float weightCalcOrigin(float finalAlpha, float zLoc, float linearizedLoc);
|
||||
float weightCalcFlat(float finalAlpha, float zLoc, float linearizedLoc);
|
||||
@ -181,125 +108,3 @@ float weightCalcNew(float finalAlpha, float zLoc, float linearizedLoc){
|
||||
float linearizeDepth(float d,float zNear,float zFar){
|
||||
return zNear * zFar / (zFar + d * (zNear - zFar));
|
||||
}
|
||||
|
||||
|
||||
|
||||
float calcLightIntensityAmbient(){
|
||||
//calculate average of ambient light
|
||||
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityTotal(vec3 normal){
|
||||
//ambient intensity
|
||||
float ambientLightIntensity = calcLightIntensityAmbient();
|
||||
|
||||
//get direct intensity
|
||||
float directLightIntensity = calcLightIntensityDir(normal);
|
||||
|
||||
//sum
|
||||
float total = ambientLightIntensity + directLightIntensity;
|
||||
return total;
|
||||
}
|
||||
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = diffuse * attenuation;
|
||||
// specular *= attenuation;
|
||||
vec3 specular = vec3(0,0,0);
|
||||
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the light cluster this fragment belongs to
|
||||
*/
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
|
||||
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
|
||||
vec2 tileSize = screenDimensions / gridSize.xy;
|
||||
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
|
||||
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||
|
||||
// perform perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
//transform to NDC
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
//get closest depth from light's POV
|
||||
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
//get depth of current fragment
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
//calculate bias
|
||||
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||
|
||||
//calculate shadow value
|
||||
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||
|
||||
if(projCoords.z > 1.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
//calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping
|
||||
//ie the fragment is already facing away from the light source
|
||||
float dotprod = dot(normalize(lightDir),normalize(normal));
|
||||
|
||||
if(dotprod > 0.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
// shadow = currentDepth;
|
||||
|
||||
return shadow;
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
#version 450 core
|
||||
#extension GL_ARB_shading_language_include : require
|
||||
#include "../../lib/lights.fs"
|
||||
|
||||
//texture defines
|
||||
#define ATLAS_ELEMENT_DIM 256.0
|
||||
@ -8,69 +10,6 @@
|
||||
#define ATLAS_NORMALIZED_ELEMENT_WIDTH_FULL 0.03125 //used to properly shift from texture to texture in the atlas
|
||||
|
||||
|
||||
/**
|
||||
Bind points for different SSBOs
|
||||
*/
|
||||
#define CLUSTER_SSBO_BIND_POINT 1
|
||||
#define POINT_LIGHT_SSBO_BIND_POINT 2
|
||||
#define DIRECT_LIGHT_SSBO_BIND_POINT 3
|
||||
|
||||
|
||||
/**
|
||||
Maximum number of point lights
|
||||
*/
|
||||
#define MAX_POINT_LIGHTS 512
|
||||
|
||||
/**
|
||||
Maximum number of lights per cluster
|
||||
*/
|
||||
#define MAX_LIGHTS_PER_CLUSTER 100
|
||||
|
||||
/**
|
||||
The direct global light
|
||||
*/
|
||||
struct DirectLight {
|
||||
vec3 direction;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
/**
|
||||
A point light
|
||||
*/
|
||||
struct PointLight {
|
||||
vec4 position;
|
||||
vec4 color;
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
float radius;
|
||||
};
|
||||
|
||||
/**
|
||||
A light cluster
|
||||
*/
|
||||
struct Cluster {
|
||||
vec4 minPoint;
|
||||
vec4 maxPoint;
|
||||
uint count;
|
||||
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
|
||||
};
|
||||
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
sampler2D specular;
|
||||
@ -86,34 +25,20 @@ in flat int samplerIndexVec; //the indices in the atlas of textures to sample
|
||||
|
||||
|
||||
uniform vec3 viewPos;
|
||||
// uniform DirLight dirLight;
|
||||
// uniform PointLight pointLights[NR_POINT_LIGHTS];
|
||||
// uniform SpotLight spotLight;
|
||||
uniform Material material;
|
||||
|
||||
//texture stuff
|
||||
// uniform sampler2D ourTexture;
|
||||
uniform int hasTransparency;
|
||||
// uniform sampler2D specularTexture;
|
||||
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
uniform mat4 view;
|
||||
|
||||
/**
|
||||
The output
|
||||
*/
|
||||
out vec4 FragColor;
|
||||
|
||||
|
||||
// function prototypes
|
||||
uint findCluster(vec3 FragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
vec3 getColor(vec2 uv, vec3 normal, int samplerIndexVec, Material material);
|
||||
|
||||
void main(){
|
||||
@ -168,122 +93,4 @@ vec3 getColor(vec2 uv, vec3 normal, int samplerIndexVec, Material material){
|
||||
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityAmbient(){
|
||||
//calculate average of ambient light
|
||||
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityTotal(vec3 normal){
|
||||
//ambient intensity
|
||||
float ambientLightIntensity = calcLightIntensityAmbient();
|
||||
|
||||
//get direct intensity
|
||||
float directLightIntensity = calcLightIntensityDir(normal);
|
||||
|
||||
//sum
|
||||
float total = ambientLightIntensity + directLightIntensity;
|
||||
return total;
|
||||
}
|
||||
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = diffuse * attenuation;
|
||||
// specular *= attenuation;
|
||||
vec3 specular = vec3(0,0,0);
|
||||
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the light cluster this fragment belongs to
|
||||
*/
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
|
||||
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
|
||||
vec2 tileSize = screenDimensions / gridSize.xy;
|
||||
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
|
||||
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
|
||||
}
|
||||
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||
|
||||
// perform perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
//transform to NDC
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
//get closest depth from light's POV
|
||||
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
//get depth of current fragment
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
//calculate bias
|
||||
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||
|
||||
//calculate shadow value
|
||||
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||
|
||||
if(projCoords.z > 1.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
//calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping
|
||||
//ie the fragment is already facing away from the light source
|
||||
float dotprod = dot(normalize(lightDir),normalize(normal));
|
||||
|
||||
if(dotprod > 0.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
// shadow = currentDepth;
|
||||
|
||||
return clamp(1.0 - shadow, 0.0, 0.7);
|
||||
}
|
||||
@ -1,70 +1,9 @@
|
||||
#version 450 core
|
||||
#extension GL_ARB_shading_language_include : require
|
||||
#include "../../lib/lights.fs"
|
||||
|
||||
//foliage.fs
|
||||
|
||||
/**
|
||||
Bind points for different SSBOs
|
||||
*/
|
||||
#define CLUSTER_SSBO_BIND_POINT 1
|
||||
#define POINT_LIGHT_SSBO_BIND_POINT 2
|
||||
#define DIRECT_LIGHT_SSBO_BIND_POINT 3
|
||||
|
||||
|
||||
/**
|
||||
Maximum number of point lights
|
||||
*/
|
||||
#define MAX_POINT_LIGHTS 512
|
||||
|
||||
/**
|
||||
Maximum number of lights per cluster
|
||||
*/
|
||||
#define MAX_LIGHTS_PER_CLUSTER 100
|
||||
|
||||
/**
|
||||
The direct global light
|
||||
*/
|
||||
struct DirectLight {
|
||||
vec3 direction;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
/**
|
||||
A point light
|
||||
*/
|
||||
struct PointLight {
|
||||
vec4 position;
|
||||
vec4 color;
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
float radius;
|
||||
};
|
||||
|
||||
/**
|
||||
A light cluster
|
||||
*/
|
||||
struct Cluster {
|
||||
vec4 minPoint;
|
||||
vec4 maxPoint;
|
||||
uint count;
|
||||
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
sampler2D specular;
|
||||
@ -91,24 +30,16 @@ uniform Material material;
|
||||
uniform int hasTransparency;
|
||||
// uniform sampler2D specularTexture;
|
||||
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
uniform mat4 view;
|
||||
|
||||
|
||||
/**
|
||||
The output
|
||||
*/
|
||||
out vec4 FragColor;
|
||||
|
||||
// function prototypes
|
||||
uint findCluster(vec3 FragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
float easeIn(float interpolator);
|
||||
float easeOut(float interpolator);
|
||||
|
||||
@ -166,143 +97,6 @@ void main(){
|
||||
FragColor = vec4(finalColor, 1.0);//texture(ourTexture, TexCoord);//vec4(result, 1.0);
|
||||
}
|
||||
|
||||
// calculates the color when using a directional light.
|
||||
// vec3 CalcDirLight(vec3 normal, vec3 viewDir){
|
||||
// vec3 lightDir = normalize(-dLDirection);
|
||||
// // diffuse shading
|
||||
// float diff = max(dot(normal, lightDir), 0.0);
|
||||
// // specular shading
|
||||
// // vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// // combine results
|
||||
// vec3 texColor = texture(material.diffuse, TexCoord).rgb;
|
||||
// vec3 diffuse = dLDiffuse * diff;
|
||||
// //vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord).rgb);
|
||||
|
||||
|
||||
// float shadow = ShadowCalculation(FragPosLightSpace, lightDir, normal);
|
||||
|
||||
// return ( dLAmbient + (1.0-shadow) * diffuse ) * texColor;// + specular);
|
||||
// }
|
||||
|
||||
//
|
||||
float calcLightIntensityAmbient(){
|
||||
//calculate average of ambient light
|
||||
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityTotal(vec3 normal){
|
||||
//ambient intensity
|
||||
float ambientLightIntensity = calcLightIntensityAmbient();
|
||||
|
||||
//get direct intensity
|
||||
float directLightIntensity = calcLightIntensityDir(normal);
|
||||
|
||||
//sum
|
||||
float total = ambientLightIntensity + directLightIntensity;
|
||||
return total;
|
||||
}
|
||||
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = diffuse * attenuation;
|
||||
// specular *= attenuation;
|
||||
vec3 specular = vec3(0,0,0);
|
||||
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the light cluster this fragment belongs to
|
||||
*/
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
|
||||
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
|
||||
vec2 tileSize = screenDimensions / gridSize.xy;
|
||||
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
|
||||
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
|
||||
}
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||
|
||||
// perform perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
//transform to NDC
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
//get closest depth from light's POV
|
||||
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
//get depth of current fragment
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
//calculate bias
|
||||
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||
|
||||
//calculate shadow value
|
||||
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||
|
||||
if(projCoords.z > 1.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
//calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping
|
||||
//ie the fragment is already facing away from the light source
|
||||
float dotprod = dot(normalize(lightDir),normalize(normal));
|
||||
|
||||
if(dotprod > 0.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
// shadow = currentDepth;
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
|
||||
float easeIn(float interpolator){
|
||||
return interpolator * interpolator;
|
||||
}
|
||||
|
||||
@ -1,71 +1,13 @@
|
||||
#version 450 core
|
||||
#extension GL_ARB_shading_language_include : require
|
||||
#include "../../lib/lights.fs"
|
||||
|
||||
//foliage.fs
|
||||
|
||||
/**
|
||||
Bind points for different SSBOs
|
||||
*/
|
||||
#define CLUSTER_SSBO_BIND_POINT 1
|
||||
#define POINT_LIGHT_SSBO_BIND_POINT 2
|
||||
#define DIRECT_LIGHT_SSBO_BIND_POINT 3
|
||||
|
||||
|
||||
/**
|
||||
Maximum number of point lights
|
||||
*/
|
||||
#define MAX_POINT_LIGHTS 512
|
||||
|
||||
/**
|
||||
Maximum number of lights per cluster
|
||||
*/
|
||||
#define MAX_LIGHTS_PER_CLUSTER 100
|
||||
|
||||
/**
|
||||
The direct global light
|
||||
*/
|
||||
struct DirectLight {
|
||||
vec3 direction;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
/**
|
||||
A point light
|
||||
*/
|
||||
struct PointLight {
|
||||
vec4 position;
|
||||
vec4 color;
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
float radius;
|
||||
};
|
||||
|
||||
/**
|
||||
A light cluster
|
||||
*/
|
||||
struct Cluster {
|
||||
vec4 minPoint;
|
||||
vec4 maxPoint;
|
||||
uint count;
|
||||
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
|
||||
};
|
||||
|
||||
layout (location = 0) out vec4 accum;
|
||||
layout (location = 1) out float reveal;
|
||||
|
||||
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
sampler2D specular;
|
||||
@ -81,34 +23,16 @@ in vec4 instanceColor;
|
||||
|
||||
|
||||
uniform vec3 viewPos;
|
||||
// uniform DirLight dirLight;
|
||||
// uniform PointLight pointLights[NR_POINT_LIGHTS];
|
||||
// uniform SpotLight spotLight;
|
||||
uniform Material material;
|
||||
|
||||
//texture stuff
|
||||
// uniform sampler2D ourTexture;
|
||||
uniform int hasTransparency;
|
||||
// uniform sampler2D specularTexture;
|
||||
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
uniform mat4 view;
|
||||
|
||||
|
||||
/**
|
||||
The output
|
||||
*/
|
||||
out vec4 FragColor;
|
||||
|
||||
// function prototypes
|
||||
uint findCluster(vec3 FragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
float easeIn(float interpolator);
|
||||
float easeOut(float interpolator);
|
||||
|
||||
@ -159,142 +83,6 @@ void main(){
|
||||
reveal = finalColor.a;
|
||||
}
|
||||
|
||||
// calculates the color when using a directional light.
|
||||
// vec3 CalcDirLight(vec3 normal, vec3 viewDir){
|
||||
// vec3 lightDir = normalize(-dLDirection);
|
||||
// // diffuse shading
|
||||
// float diff = max(dot(normal, lightDir), 0.0);
|
||||
// // specular shading
|
||||
// // vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// // combine results
|
||||
// vec3 texColor = texture(material.diffuse, TexCoord).rgb;
|
||||
// vec3 diffuse = dLDiffuse * diff;
|
||||
// //vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord).rgb);
|
||||
|
||||
|
||||
// float shadow = ShadowCalculation(FragPosLightSpace, lightDir, normal);
|
||||
|
||||
// return ( dLAmbient + (1.0-shadow) * diffuse ) * texColor;// + specular);
|
||||
// }
|
||||
|
||||
//
|
||||
float calcLightIntensityAmbient(){
|
||||
//calculate average of ambient light
|
||||
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityTotal(vec3 normal){
|
||||
//ambient intensity
|
||||
float ambientLightIntensity = calcLightIntensityAmbient();
|
||||
|
||||
//get direct intensity
|
||||
float directLightIntensity = calcLightIntensityDir(normal);
|
||||
|
||||
//sum
|
||||
float total = ambientLightIntensity + directLightIntensity;
|
||||
return total;
|
||||
}
|
||||
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = diffuse * attenuation;
|
||||
// specular *= attenuation;
|
||||
vec3 specular = vec3(0,0,0);
|
||||
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the light cluster this fragment belongs to
|
||||
*/
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
|
||||
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
|
||||
vec2 tileSize = screenDimensions / gridSize.xy;
|
||||
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
|
||||
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
|
||||
}
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||
|
||||
// perform perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
//transform to NDC
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
//get closest depth from light's POV
|
||||
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
//get depth of current fragment
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
//calculate bias
|
||||
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||
|
||||
//calculate shadow value
|
||||
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||
|
||||
if(projCoords.z > 1.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
//calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping
|
||||
//ie the fragment is already facing away from the light source
|
||||
float dotprod = dot(normalize(lightDir),normalize(normal));
|
||||
|
||||
if(dotprod > 0.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
// shadow = currentDepth;
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
|
||||
float easeIn(float interpolator){
|
||||
return interpolator * interpolator;
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
#version 450 core
|
||||
#extension GL_ARB_shading_language_include : require
|
||||
#include "../../lib/lights.fs"
|
||||
|
||||
//texture defines
|
||||
#define ATLAS_ELEMENT_DIM 256.0
|
||||
@ -8,69 +10,6 @@
|
||||
#define ATLAS_NORMALIZED_ELEMENT_WIDTH_FULL 0.03125 //used to properly shift from texture to texture in the atlas
|
||||
|
||||
|
||||
/**
|
||||
Bind points for different SSBOs
|
||||
*/
|
||||
#define CLUSTER_SSBO_BIND_POINT 1
|
||||
#define POINT_LIGHT_SSBO_BIND_POINT 2
|
||||
#define DIRECT_LIGHT_SSBO_BIND_POINT 3
|
||||
|
||||
|
||||
/**
|
||||
Maximum number of point lights
|
||||
*/
|
||||
#define MAX_POINT_LIGHTS 512
|
||||
|
||||
/**
|
||||
Maximum number of lights per cluster
|
||||
*/
|
||||
#define MAX_LIGHTS_PER_CLUSTER 100
|
||||
|
||||
/**
|
||||
The direct global light
|
||||
*/
|
||||
struct DirectLight {
|
||||
vec3 direction;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
/**
|
||||
A point light
|
||||
*/
|
||||
struct PointLight {
|
||||
vec4 position;
|
||||
vec4 color;
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
float radius;
|
||||
};
|
||||
|
||||
/**
|
||||
A light cluster
|
||||
*/
|
||||
struct Cluster {
|
||||
vec4 minPoint;
|
||||
vec4 maxPoint;
|
||||
uint count;
|
||||
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
|
||||
};
|
||||
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
sampler2D specular;
|
||||
@ -93,30 +32,15 @@ uniform vec3 viewPos;
|
||||
// uniform PointLight pointLights[NR_POINT_LIGHTS];
|
||||
// uniform SpotLight spotLight;
|
||||
uniform Material material;
|
||||
|
||||
//texture stuff
|
||||
// uniform sampler2D ourTexture;
|
||||
uniform int hasTransparency;
|
||||
// uniform sampler2D specularTexture;
|
||||
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
uniform mat4 view;
|
||||
|
||||
|
||||
/**
|
||||
The output
|
||||
*/
|
||||
out vec4 FragColor;
|
||||
|
||||
// function prototypes
|
||||
uint findCluster(vec3 FragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
vec3 getColor(vec2 texPlane1, vec2 texPlane2, vec2 texPlane3, vec3 normal, vec3 samplerIndexVec, vec3 samplerRatioVec, Material material);
|
||||
|
||||
void main(){
|
||||
@ -234,121 +158,3 @@ vec3 getColor(vec2 texPlane1, vec2 texPlane2, vec2 texPlane3, vec3 normal, vec3
|
||||
|
||||
return (albedoX * weights.x + albedoY * weights.y + albedoZ * weights.z);
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityAmbient(){
|
||||
//calculate average of ambient light
|
||||
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityTotal(vec3 normal){
|
||||
//ambient intensity
|
||||
float ambientLightIntensity = calcLightIntensityAmbient();
|
||||
|
||||
//get direct intensity
|
||||
float directLightIntensity = calcLightIntensityDir(normal);
|
||||
|
||||
//sum
|
||||
float total = ambientLightIntensity + directLightIntensity;
|
||||
return total;
|
||||
}
|
||||
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = diffuse * attenuation;
|
||||
// specular *= attenuation;
|
||||
vec3 specular = vec3(0,0,0);
|
||||
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the light cluster this fragment belongs to
|
||||
*/
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
|
||||
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
|
||||
vec2 tileSize = screenDimensions / gridSize.xy;
|
||||
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
|
||||
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
|
||||
}
|
||||
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||
|
||||
// perform perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
//transform to NDC
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
//get closest depth from light's POV
|
||||
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
//get depth of current fragment
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
//calculate bias
|
||||
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||
|
||||
//calculate shadow value
|
||||
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||
|
||||
if(projCoords.z > 1.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
//calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping
|
||||
//ie the fragment is already facing away from the light source
|
||||
float dotprod = dot(normalize(lightDir),normalize(normal));
|
||||
|
||||
if(dotprod > 0.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
// shadow = currentDepth;
|
||||
|
||||
return clamp(1.0 - shadow, 0.0, 0.7);
|
||||
}
|
||||
@ -1,74 +1,12 @@
|
||||
#version 450 core
|
||||
#extension GL_ARB_shading_language_include : require
|
||||
#include "../../lib/lights.fs"
|
||||
|
||||
//colorshift.fs
|
||||
|
||||
/**
|
||||
Bind points for different SSBOs
|
||||
*/
|
||||
#define CLUSTER_SSBO_BIND_POINT 1
|
||||
#define POINT_LIGHT_SSBO_BIND_POINT 2
|
||||
#define DIRECT_LIGHT_SSBO_BIND_POINT 3
|
||||
|
||||
|
||||
/**
|
||||
Maximum number of point lights
|
||||
*/
|
||||
#define MAX_POINT_LIGHTS 512
|
||||
|
||||
/**
|
||||
Maximum number of lights per cluster
|
||||
*/
|
||||
#define MAX_LIGHTS_PER_CLUSTER 100
|
||||
|
||||
/**
|
||||
transparency
|
||||
*/
|
||||
#define SMALL_EPSILON 0.001
|
||||
|
||||
/**
|
||||
The direct global light
|
||||
*/
|
||||
struct DirectLight {
|
||||
vec3 direction;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
/**
|
||||
A point light
|
||||
*/
|
||||
struct PointLight {
|
||||
vec4 position;
|
||||
vec4 color;
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
float radius;
|
||||
};
|
||||
|
||||
/**
|
||||
A light cluster
|
||||
*/
|
||||
struct Cluster {
|
||||
vec4 minPoint;
|
||||
vec4 maxPoint;
|
||||
uint count;
|
||||
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
@ -87,27 +25,13 @@ in vec3 colorShiftValue;
|
||||
uniform vec3 viewPos;
|
||||
uniform Material material;
|
||||
|
||||
//texture stuff
|
||||
uniform int hasTransparency;
|
||||
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
uniform mat4 view;
|
||||
|
||||
/**
|
||||
The output
|
||||
*/
|
||||
out vec4 FragColor;
|
||||
|
||||
// function prototypes
|
||||
uint findCluster(vec3 FragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
|
||||
void main(){
|
||||
|
||||
@ -157,140 +81,3 @@ void main(){
|
||||
//this final calculation is for transparency
|
||||
FragColor = vec4(finalColor, 1);//texture(ourTexture, TexCoord);//vec4(result, 1.0);
|
||||
}
|
||||
|
||||
// calculates the color when using a directional light.
|
||||
// vec3 CalcDirLight(vec3 normal, vec3 viewDir){
|
||||
// vec3 lightDir = normalize(-dLDirection);
|
||||
// // diffuse shading
|
||||
// float diff = max(dot(normal, lightDir), 0.0);
|
||||
// // specular shading
|
||||
// // vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// // combine results
|
||||
// vec3 texColor = texture(material.diffuse, TexCoord).rgb;
|
||||
// vec3 diffuse = dLDiffuse * diff;
|
||||
// //vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord).rgb);
|
||||
|
||||
|
||||
// float shadow = ShadowCalculation(FragPosLightSpace, lightDir, normal);
|
||||
|
||||
// return ( dLAmbient + (1.0-shadow) * diffuse ) * texColor;// + specular);
|
||||
// }
|
||||
|
||||
//
|
||||
float calcLightIntensityAmbient(){
|
||||
//calculate average of ambient light
|
||||
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityTotal(vec3 normal){
|
||||
//ambient intensity
|
||||
float ambientLightIntensity = calcLightIntensityAmbient();
|
||||
|
||||
//get direct intensity
|
||||
float directLightIntensity = calcLightIntensityDir(normal);
|
||||
|
||||
//sum
|
||||
float total = ambientLightIntensity + directLightIntensity;
|
||||
return total;
|
||||
}
|
||||
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = diffuse * attenuation;
|
||||
// specular *= attenuation;
|
||||
vec3 specular = vec3(0,0,0);
|
||||
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the light cluster this fragment belongs to
|
||||
*/
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
|
||||
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
|
||||
vec2 tileSize = screenDimensions / gridSize.xy;
|
||||
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
|
||||
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
|
||||
}
|
||||
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||
|
||||
// perform perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
//transform to NDC
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
//get closest depth from light's POV
|
||||
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
//get depth of current fragment
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
//calculate bias
|
||||
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||
|
||||
//calculate shadow value
|
||||
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||
|
||||
if(projCoords.z > 1.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
//calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping
|
||||
//ie the fragment is already facing away from the light source
|
||||
float dotprod = dot(normalize(lightDir),normalize(normal));
|
||||
|
||||
if(dotprod > 0.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
// shadow = currentDepth;
|
||||
|
||||
return shadow;
|
||||
}
|
||||
@ -1,41 +1,13 @@
|
||||
#version 330 core
|
||||
#version 450 core
|
||||
#extension GL_ARB_shading_language_include : require
|
||||
#include "../../lib/lights.fs"
|
||||
|
||||
//generic.fs
|
||||
|
||||
#define NR_POINT_LIGHTS 10
|
||||
|
||||
#define SMALL_EPSILON 0.0001
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
|
||||
layout (std140) uniform Lights {
|
||||
// this is how many because we have to align
|
||||
// bytes it SHOULD in multiples of 16, this
|
||||
// take it where it ACTUALLY is
|
||||
//
|
||||
//refer: https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL
|
||||
//
|
||||
// base alignment aligned offset
|
||||
//direct light
|
||||
vec3 dLDirection; // 16 0
|
||||
vec3 dLAmbient; // 16 16
|
||||
vec3 dLDiffuse; // 16 32
|
||||
vec3 dLSpecular; // 16 48
|
||||
|
||||
//point light
|
||||
vec3 pLposition[NR_POINT_LIGHTS]; // 16*10 64
|
||||
float pLconstant[NR_POINT_LIGHTS]; // 16*10 224
|
||||
float pLlinear[NR_POINT_LIGHTS]; // 16*10 384
|
||||
float pLquadratic[NR_POINT_LIGHTS]; // 16*10 544
|
||||
vec3 pLambient[NR_POINT_LIGHTS]; // 16*10 704
|
||||
vec3 pLdiffuse[NR_POINT_LIGHTS]; // 16*10 864
|
||||
vec3 pLspecular[NR_POINT_LIGHTS]; // 16*10 1024
|
||||
|
||||
//for a total size of 1184
|
||||
|
||||
};
|
||||
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
sampler2D specular;
|
||||
@ -54,21 +26,6 @@ uniform vec3 viewPos;
|
||||
// uniform SpotLight spotLight;
|
||||
uniform Material material;
|
||||
|
||||
//texture stuff
|
||||
// uniform sampler2D ourTexture;
|
||||
uniform int hasTransparency;
|
||||
// uniform sampler2D specularTexture;
|
||||
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
|
||||
// function prototypes
|
||||
// vec3 CalcDirLight(vec3 normal, vec3 viewDir);
|
||||
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
// vec3 CalcSpotLight(vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
|
||||
void main(){
|
||||
|
||||
@ -86,7 +43,7 @@ void main(){
|
||||
vec3 textureColor = texture(material.diffuse, TexCoord).rgb;
|
||||
|
||||
//shadow
|
||||
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-dLDirection), norm);
|
||||
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), norm);
|
||||
|
||||
//calculate final color
|
||||
vec3 finalColor = textureColor * lightIntensity * max(shadow,0.4);
|
||||
@ -98,150 +55,3 @@ void main(){
|
||||
//this final calculation is for transparency
|
||||
FragColor = vec4(finalColor, 1);//texture(ourTexture, TexCoord);//vec4(result, 1.0);
|
||||
}
|
||||
|
||||
// calculates the color when using a directional light.
|
||||
// vec3 CalcDirLight(vec3 normal, vec3 viewDir){
|
||||
// vec3 lightDir = normalize(-dLDirection);
|
||||
// // diffuse shading
|
||||
// float diff = max(dot(normal, lightDir), 0.0);
|
||||
// // specular shading
|
||||
// // vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// // combine results
|
||||
// vec3 texColor = texture(material.diffuse, TexCoord).rgb;
|
||||
// vec3 diffuse = dLDiffuse * diff;
|
||||
// //vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord).rgb);
|
||||
|
||||
|
||||
// float shadow = ShadowCalculation(FragPosLightSpace, lightDir, normal);
|
||||
|
||||
// return ( dLAmbient + (1.0-shadow) * diffuse ) * texColor;// + specular);
|
||||
// }
|
||||
|
||||
//
|
||||
float calcLightIntensityAmbient(){
|
||||
//calculate average of ambient light
|
||||
float avg = (dLAmbient.x + dLAmbient.y + dLAmbient.z)/3.0;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-dLDirection);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityTotal(vec3 normal){
|
||||
//ambient intensity
|
||||
float ambientLightIntensity = calcLightIntensityAmbient();
|
||||
|
||||
//get direct intensity
|
||||
float directLightIntensity = calcLightIntensityDir(normal);
|
||||
|
||||
//sum
|
||||
float total = ambientLightIntensity + directLightIntensity;
|
||||
return total;
|
||||
}
|
||||
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pLposition[i] - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pLposition[i] - fragPos);
|
||||
float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance));
|
||||
// combine results
|
||||
vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient *= attenuation;
|
||||
diffuse *= attenuation;
|
||||
// specular *= attenuation;
|
||||
vec3 specular = vec3(0,0,0);
|
||||
|
||||
vec3 finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
// // calculates the color when using a point light.
|
||||
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
// vec3 lightDir = normalize(pLposition[i] - fragPos);
|
||||
// // diffuse shading
|
||||
// float diff = max(dot(normal, lightDir), 0.0);
|
||||
// // specular shading
|
||||
// // vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// // attenuation
|
||||
// float distance = length(pLposition[i] - fragPos);
|
||||
// float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance));
|
||||
// // combine results
|
||||
// vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// // vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
// ambient *= attenuation;
|
||||
// diffuse *= attenuation;
|
||||
// // specular *= attenuation;
|
||||
// vec3 specular = vec3(0,0,0);
|
||||
|
||||
// vec3 finalValue = (ambient + diffuse + specular);
|
||||
// finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
|
||||
// return finalValue;
|
||||
// }
|
||||
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||
|
||||
// perform perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
//transform to NDC
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
//get closest depth from light's POV
|
||||
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
//get depth of current fragment
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
//calculate bias
|
||||
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||
|
||||
//calculate shadow value
|
||||
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||
|
||||
if(projCoords.z > 1.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
//calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping
|
||||
//ie the fragment is already facing away from the light source
|
||||
float dotprod = dot(normalize(lightDir),normalize(normal));
|
||||
|
||||
if(dotprod > 0.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
// shadow = currentDepth;
|
||||
|
||||
return shadow;
|
||||
}
|
||||
@ -1,70 +1,9 @@
|
||||
#version 450 core
|
||||
#extension GL_ARB_shading_language_include : require
|
||||
#include "../../lib/lights.fs"
|
||||
|
||||
//proceduraltree.fs
|
||||
|
||||
/**
|
||||
Bind points for different SSBOs
|
||||
*/
|
||||
#define CLUSTER_SSBO_BIND_POINT 1
|
||||
#define POINT_LIGHT_SSBO_BIND_POINT 2
|
||||
#define DIRECT_LIGHT_SSBO_BIND_POINT 3
|
||||
|
||||
|
||||
/**
|
||||
Maximum number of point lights
|
||||
*/
|
||||
#define MAX_POINT_LIGHTS 512
|
||||
|
||||
/**
|
||||
Maximum number of lights per cluster
|
||||
*/
|
||||
#define MAX_LIGHTS_PER_CLUSTER 100
|
||||
|
||||
/**
|
||||
The direct global light
|
||||
*/
|
||||
struct DirectLight {
|
||||
vec3 direction;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
/**
|
||||
A point light
|
||||
*/
|
||||
struct PointLight {
|
||||
vec4 position;
|
||||
vec4 color;
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
float radius;
|
||||
};
|
||||
|
||||
/**
|
||||
A light cluster
|
||||
*/
|
||||
struct Cluster {
|
||||
vec4 minPoint;
|
||||
vec4 maxPoint;
|
||||
uint count;
|
||||
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
sampler2D diffuse;
|
||||
sampler2D specular;
|
||||
@ -79,34 +18,16 @@ in vec4 FragPosLightSpace;
|
||||
|
||||
|
||||
uniform vec3 viewPos;
|
||||
// uniform DirLight dirLight;
|
||||
// uniform PointLight pointLights[NR_POINT_LIGHTS];
|
||||
// uniform SpotLight spotLight;
|
||||
uniform Material material;
|
||||
|
||||
//texture stuff
|
||||
// uniform sampler2D ourTexture;
|
||||
uniform int hasTransparency;
|
||||
// uniform sampler2D specularTexture;
|
||||
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
uniform mat4 view;
|
||||
|
||||
|
||||
// function prototypes
|
||||
uint findCluster(vec3 FragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
/**
|
||||
The output
|
||||
*/
|
||||
out vec4 FragColor;
|
||||
|
||||
|
||||
void main(){
|
||||
vec3 norm = normalize(Normal);
|
||||
@ -138,148 +59,7 @@ void main(){
|
||||
|
||||
//calculate final color
|
||||
vec3 finalColor = textureColor * lightIntensity;
|
||||
// vec3 lightAmount = CalcDirLight(norm, viewDir);
|
||||
// for(int i = 0; i < NR_POINT_LIGHTS; i++){
|
||||
// lightAmount += CalcPointLight(i, norm, FragPos, viewDir);
|
||||
// }
|
||||
|
||||
//this final calculation is for transparency
|
||||
FragColor = vec4(finalColor, texture(material.diffuse, TexCoord).a);//texture(ourTexture, TexCoord);//vec4(result, 1.0);
|
||||
FragColor = vec4(finalColor, texture(material.diffuse, TexCoord).a);
|
||||
}
|
||||
|
||||
// calculates the color when using a directional light.
|
||||
// vec3 CalcDirLight(vec3 normal, vec3 viewDir){
|
||||
// vec3 lightDir = normalize(-dLDirection);
|
||||
// // diffuse shading
|
||||
// float diff = max(dot(normal, lightDir), 0.0);
|
||||
// // specular shading
|
||||
// // vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// // combine results
|
||||
// vec3 texColor = texture(material.diffuse, TexCoord).rgb;
|
||||
// vec3 diffuse = dLDiffuse * diff;
|
||||
// //vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord).rgb);
|
||||
|
||||
|
||||
// float shadow = ShadowCalculation(FragPosLightSpace, lightDir, normal);
|
||||
|
||||
// return ( dLAmbient + (1.0-shadow) * diffuse ) * texColor;// + specular);
|
||||
// }
|
||||
|
||||
//
|
||||
float calcLightIntensityAmbient(){
|
||||
//calculate average of ambient light
|
||||
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityTotal(vec3 normal){
|
||||
//ambient intensity
|
||||
float ambientLightIntensity = calcLightIntensityAmbient();
|
||||
|
||||
//get direct intensity
|
||||
float directLightIntensity = calcLightIntensityDir(normal);
|
||||
|
||||
//sum
|
||||
float total = ambientLightIntensity + directLightIntensity;
|
||||
return total;
|
||||
}
|
||||
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = diffuse * attenuation;
|
||||
// specular *= attenuation;
|
||||
vec3 specular = vec3(0,0,0);
|
||||
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the light cluster this fragment belongs to
|
||||
*/
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
|
||||
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
|
||||
vec2 tileSize = screenDimensions / gridSize.xy;
|
||||
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
|
||||
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
|
||||
}
|
||||
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||
|
||||
// perform perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
//transform to NDC
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
//get closest depth from light's POV
|
||||
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
//get depth of current fragment
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
//calculate bias
|
||||
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||
|
||||
//calculate shadow value
|
||||
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||
|
||||
if(projCoords.z > 1.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
//calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping
|
||||
//ie the fragment is already facing away from the light source
|
||||
float dotprod = dot(normalize(lightDir),normalize(normal));
|
||||
|
||||
if(dotprod > 0.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
// shadow = currentDepth;
|
||||
|
||||
return shadow;
|
||||
}
|
||||
209
assets/Shaders/lib/lights.fs
Normal file
209
assets/Shaders/lib/lights.fs
Normal file
@ -0,0 +1,209 @@
|
||||
//uncomment if working on this library file:
|
||||
//#version 450 core
|
||||
|
||||
/**
|
||||
Maximum number of point lights
|
||||
*/
|
||||
#define MAX_POINT_LIGHTS 512
|
||||
|
||||
/**
|
||||
Maximum number of lights per cluster
|
||||
*/
|
||||
#define MAX_LIGHTS_PER_CLUSTER 100
|
||||
|
||||
/**
|
||||
Bind points for different SSBOs
|
||||
*/
|
||||
#define CLUSTER_SSBO_BIND_POINT 1
|
||||
#define POINT_LIGHT_SSBO_BIND_POINT 2
|
||||
#define DIRECT_LIGHT_SSBO_BIND_POINT 3
|
||||
|
||||
/**
|
||||
The direct global light
|
||||
*/
|
||||
struct DirectLight {
|
||||
vec3 direction;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
/**
|
||||
A point light
|
||||
*/
|
||||
struct PointLight {
|
||||
vec4 position;
|
||||
vec4 color;
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
float radius;
|
||||
};
|
||||
|
||||
/**
|
||||
A light cluster
|
||||
*/
|
||||
struct Cluster {
|
||||
vec4 minPoint;
|
||||
vec4 maxPoint;
|
||||
uint count;
|
||||
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
|
||||
};
|
||||
|
||||
/**
|
||||
Cutoff for fragment alpha
|
||||
*/
|
||||
#define FRAGMENT_ALPHA_CUTOFF 0.001
|
||||
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
|
||||
/**
|
||||
The light depth map texture
|
||||
*/
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
|
||||
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
|
||||
|
||||
|
||||
float calcLightIntensityAmbient(){
|
||||
//calculate average of ambient light
|
||||
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityTotal(vec3 normal){
|
||||
//ambient intensity
|
||||
float ambientLightIntensity = calcLightIntensityAmbient();
|
||||
|
||||
//get direct intensity
|
||||
float directLightIntensity = calcLightIntensityDir(normal);
|
||||
|
||||
//sum
|
||||
float total = ambientLightIntensity + directLightIntensity;
|
||||
return total;
|
||||
}
|
||||
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = diffuse * attenuation;
|
||||
// specular *= attenuation;
|
||||
vec3 specular = vec3(0,0,0);
|
||||
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the light cluster this fragment belongs to
|
||||
*/
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
|
||||
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
|
||||
vec2 tileSize = screenDimensions / gridSize.xy;
|
||||
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
|
||||
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
|
||||
}
|
||||
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||
|
||||
// perform perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
//transform to NDC
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
//get closest depth from light's POV
|
||||
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
//get depth of current fragment
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
//calculate bias
|
||||
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||
|
||||
//calculate shadow value
|
||||
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||
|
||||
if(projCoords.z > 1.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
//calculate dot product, if it is >0 we know they're parallel-ish therefore should disregard the shadow mapping
|
||||
//ie the fragment is already facing away from the light source
|
||||
float dotprod = dot(normalize(lightDir),normalize(normal));
|
||||
|
||||
if(dotprod > 0.0){
|
||||
shadow = 0.0;
|
||||
}
|
||||
|
||||
// shadow = currentDepth;
|
||||
|
||||
return clamp(1.0 - shadow, 0.0, 0.7);
|
||||
}
|
||||
@ -1161,6 +1161,7 @@ Remove unused import
|
||||
Geometry mesh generation class
|
||||
Cloud shader
|
||||
VisualShader refactoring
|
||||
VisualShader #include macro implementation
|
||||
|
||||
|
||||
# TODO
|
||||
|
||||
@ -9,6 +9,12 @@ public class AssetDataStrings {
|
||||
public static final String BITMAP_CHARACTER_MODEL = "bitmapCharacterModel";
|
||||
public static final String LEAVES_MODEL = "leaves";
|
||||
|
||||
/**
|
||||
* Shaders
|
||||
*/
|
||||
public static final String SHADER_DEFAULT_VERT = "Shaders/VertexShader.vs";
|
||||
public static final String SHADER_DEFAULT_FRAG = "Shaders/FragmentShader.fs";
|
||||
|
||||
/**
|
||||
* The basic geometry of the engine
|
||||
*/
|
||||
|
||||
@ -1,19 +1,21 @@
|
||||
package electrosphere.renderer.shader;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.management.RuntimeErrorException;
|
||||
|
||||
import org.lwjgl.opengl.GL40;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.engine.assetmanager.AssetDataStrings;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.OpenGLState;
|
||||
import electrosphere.renderer.RenderingEngine;
|
||||
@ -50,6 +52,46 @@ public class VisualShader implements Shader {
|
||||
* The map of path -> already compiled shader
|
||||
*/
|
||||
static Map<String,VisualShader> alreadyCompiledMap = new HashMap<String,VisualShader>();
|
||||
|
||||
|
||||
/**
|
||||
* Recursively preprocesses a file
|
||||
* @param currentFile The file to preprocess
|
||||
* @return The contents of the file
|
||||
*/
|
||||
private static String recursivelyPreprocessFile(String input){
|
||||
return VisualShader.recursivelyPreprocessFile(FileUtils.getAssetFile(input), new LinkedList<String>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively preprocesses a file
|
||||
* @param currentFile The file to preprocess
|
||||
* @return The contents of the file
|
||||
*/
|
||||
private static String recursivelyPreprocessFile(File currentFile, List<String> includes){
|
||||
String contents = null;
|
||||
try {
|
||||
contents = Files.readString(currentFile.toPath());
|
||||
} catch (IOException e) {
|
||||
LoggerInterface.loggerRenderer.ERROR(e);
|
||||
}
|
||||
Pattern includePattern = Pattern.compile("#include \"(.*)\"");
|
||||
Matcher matcher = includePattern.matcher(contents);
|
||||
int i = 1;
|
||||
while(matcher.find()){
|
||||
String group = matcher.group(i);
|
||||
if(!includes.contains(group)){
|
||||
File directory = currentFile.getParentFile();
|
||||
File newFile = new File(directory.getPath() + "/" + group);
|
||||
String includeContent = VisualShader.recursivelyPreprocessFile(newFile, includes);
|
||||
contents = contents.replace("#include \"" + group + "\"", includeContent);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
//remove strings that we don't want to include
|
||||
contents = contents.replace("#extension GL_ARB_shading_language_include : require","");
|
||||
return contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Smart assembles a shader
|
||||
@ -80,43 +122,8 @@ public class VisualShader implements Shader {
|
||||
//
|
||||
//Read in shader programs
|
||||
//
|
||||
String tempForReadingShaders = "";
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(FileUtils.getAssetFileAsStream(vertex_shader_path)));
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line = br.readLine();
|
||||
|
||||
while (line != null) {
|
||||
sb.append(line);
|
||||
sb.append(System.lineSeparator());
|
||||
line = br.readLine();
|
||||
}
|
||||
tempForReadingShaders = sb.toString();
|
||||
} finally {
|
||||
br.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
String vertexShaderSource = tempForReadingShaders;
|
||||
//This try-catch block reads the FragmentShader source into memory
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(FileUtils.getAssetFileAsStream(fragment_shader_path)));
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line = br.readLine();
|
||||
while (line != null) {
|
||||
sb.append(line);
|
||||
sb.append(System.lineSeparator());
|
||||
line = br.readLine();
|
||||
}
|
||||
tempForReadingShaders = sb.toString();
|
||||
} finally {
|
||||
br.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
String fragmentShaderSource = tempForReadingShaders;
|
||||
String vertexShaderSource = VisualShader.recursivelyPreprocessFile(vertex_shader_path);
|
||||
String fragmentShaderSource = VisualShader.recursivelyPreprocessFile(fragment_shader_path);
|
||||
//Creates a new shader object and assigns its 'pointer' to the integer "vertexShader"
|
||||
rVal.vertexShader = GL40.glCreateShader(GL40.GL_VERTEX_SHADER);
|
||||
//This alerts openGL to the presence of a vertex shader and points the shader at its source
|
||||
@ -200,43 +207,8 @@ public class VisualShader implements Shader {
|
||||
//
|
||||
//Read in shader programs
|
||||
//
|
||||
String tempForReadingShaders = "";
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(FileUtils.getAssetFileAsStream(vertex_shader_path)));
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line = br.readLine();
|
||||
|
||||
while (line != null) {
|
||||
sb.append(line);
|
||||
sb.append(System.lineSeparator());
|
||||
line = br.readLine();
|
||||
}
|
||||
tempForReadingShaders = sb.toString();
|
||||
} finally {
|
||||
br.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
String vertexShaderSource = tempForReadingShaders;
|
||||
//This try-catch block reads the FragmentShader source into memory
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(FileUtils.getAssetFileAsStream(fragment_shader_path)));
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line = br.readLine();
|
||||
while (line != null) {
|
||||
sb.append(line);
|
||||
sb.append(System.lineSeparator());
|
||||
line = br.readLine();
|
||||
}
|
||||
tempForReadingShaders = sb.toString();
|
||||
} finally {
|
||||
br.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
String fragmentShaderSource = tempForReadingShaders;
|
||||
String vertexShaderSource = VisualShader.recursivelyPreprocessFile(vertex_shader_path);
|
||||
String fragmentShaderSource = VisualShader.recursivelyPreprocessFile(fragment_shader_path);
|
||||
//Creates a new shader object and assigns its 'pointer' to the integer "vertexShader"
|
||||
rVal.vertexShader = GL40.glCreateShader(GL40.GL_VERTEX_SHADER);
|
||||
//This alerts openGL to the presence of a vertex shader and points the shader at its source
|
||||
@ -305,43 +277,8 @@ public class VisualShader implements Shader {
|
||||
//
|
||||
//Read in shader programs
|
||||
//
|
||||
String tempForReadingShaders = "";
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new FileReader(FileUtils.getAssetFile("/Shaders/VertexShader.vs")));
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line = br.readLine();
|
||||
|
||||
while (line != null) {
|
||||
sb.append(line);
|
||||
sb.append(System.lineSeparator());
|
||||
line = br.readLine();
|
||||
}
|
||||
tempForReadingShaders = sb.toString();
|
||||
} finally {
|
||||
br.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
String vertexShaderSource = tempForReadingShaders;
|
||||
//This try-catch block reads the FragmentShader source into memory
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new FileReader(FileUtils.getAssetFile("/Shaders/FragmentShader.fs")));
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line = br.readLine();
|
||||
while (line != null) {
|
||||
sb.append(line);
|
||||
sb.append(System.lineSeparator());
|
||||
line = br.readLine();
|
||||
}
|
||||
tempForReadingShaders = sb.toString();
|
||||
} finally {
|
||||
br.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
String fragmentShaderSource = tempForReadingShaders;
|
||||
String vertexShaderSource = VisualShader.recursivelyPreprocessFile(AssetDataStrings.SHADER_DEFAULT_VERT);
|
||||
String fragmentShaderSource = VisualShader.recursivelyPreprocessFile(AssetDataStrings.SHADER_DEFAULT_FRAG);
|
||||
//Creates a new shader object and assigns its 'pointer' to the integer "vertexShader"
|
||||
rVal.vertexShader = GL40.glCreateShader(GL40.GL_VERTEX_SHADER);
|
||||
//This alerts openGL to the presence of a vertex shader and points the shader at its source
|
||||
@ -405,14 +342,8 @@ public class VisualShader implements Shader {
|
||||
//
|
||||
//Read in shader programs
|
||||
//
|
||||
String vertexShaderSource = "";
|
||||
String fragmentShaderSource = "";
|
||||
try {
|
||||
vertexShaderSource = FileUtils.getAssetFileAsString(vertexPath);
|
||||
fragmentShaderSource = FileUtils.getAssetFileAsString(fragmentPath);
|
||||
} catch(IOException ex){
|
||||
|
||||
}
|
||||
String vertexShaderSource = VisualShader.recursivelyPreprocessFile(vertexPath);
|
||||
String fragmentShaderSource = VisualShader.recursivelyPreprocessFile(fragmentPath);
|
||||
//Creates a new shader object and assigns its 'pointer' to the integer "vertexShader"
|
||||
rVal.vertexShader = GL40.glCreateShader(GL40.GL_VERTEX_SHADER);
|
||||
//This alerts openGL to the presence of a vertex shader and points the shader at its source
|
||||
|
||||
Loading…
Reference in New Issue
Block a user