clustered lighting implementation
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2024-09-19 11:29:04 -04:00
parent 5eeb281e0b
commit dc52e375e3
30 changed files with 1211 additions and 632 deletions

View File

@ -1,37 +1,66 @@
#version 330 core #version 450 core
//FragmentShader.fs //FragmentShader.fs
#define NR_POINT_LIGHTS 10 /**
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];
};
out vec4 FragColor; out vec4 FragColor;
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
Cluster clusters[];
};
layout (std140) uniform Lights { layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
// this is how many because we have to align PointLight pointLight[];
// 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
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
DirectLight directLight;
}; };
struct Material { struct Material {
@ -41,6 +70,7 @@ struct Material {
}; };
in vec3 FragPos; in vec3 FragPos;
in vec3 ViewFragPos;
in vec3 Normal; in vec3 Normal;
in vec2 TexCoord; in vec2 TexCoord;
in vec4 FragPosLightSpace; in vec4 FragPosLightSpace;
@ -60,11 +90,18 @@ uniform int hasTransparency;
//light depth map //light depth map
uniform sampler2D shadowMap; uniform sampler2D shadowMap;
/**
Used for light cluster calculation
*/
uniform float zNear;
uniform float zFar;
uniform uvec3 gridSize;
uniform uvec2 screenDimensions;
// function prototypes // function prototypes
// vec3 CalcDirLight(vec3 normal, vec3 viewDir); uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar);
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir); vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
// vec3 CalcSpotLight(vec3 normal, vec3 fragPos, vec3 viewDir);
float calcLightIntensityTotal(vec3 normal); float calcLightIntensityTotal(vec3 normal);
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal); float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
@ -76,54 +113,47 @@ void main(){
vec3 viewDir = normalize(viewPos - FragPos); vec3 viewDir = normalize(viewPos - FragPos);
//grab light intensity //grab light intensity
float lightIntensity = calcLightIntensityTotal(norm); vec3 lightIntensity = vec3(calcLightIntensityTotal(norm));
//get color of base texture //get color of base texture
vec3 textureColor = texture(material.diffuse, TexCoord).rgb; vec3 textureColor = texture(material.diffuse, TexCoord).rgb;
//shadow //shadow
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-dLDirection), norm); float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), norm);
//
//point light calculations
vec3 lightAmount = vec3(0);
uint clusterIndex = findCluster(ViewFragPos, zNear, zFar);
uint pointLightCount = clusters[clusterIndex].count;
for(int i = 0; i < pointLightCount; i++){
uint pointLightIndex = clusters[clusterIndex].lightIndices[i];
PointLight pointLight = pointLight[pointLightIndex];
lightIntensity = lightIntensity + CalcPointLight(pointLight, norm, FragPos, viewDir);
}
//error checking on light clusters
if(pointLightCount > MAX_LIGHTS_PER_CLUSTER){
FragColor = vec4(1.0f,0,0,1.0f);
return;
}
//calculate final color //calculate final color
vec3 finalColor = textureColor * lightIntensity * max(shadow,0.4); vec3 finalColor = textureColor * lightIntensity * max(shadow,0.4);
// 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 //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);//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(){ float calcLightIntensityAmbient(){
//calculate average of ambient light //calculate average of ambient light
float avg = (dLAmbient.x + dLAmbient.y + dLAmbient.z)/3.0; float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
return avg; return avg;
} }
// //
float calcLightIntensityDir(vec3 normal){ float calcLightIntensityDir(vec3 normal){
vec3 lightDir = normalize(-dLDirection); vec3 lightDir = normalize(-directLight.direction);
// diffuse shading // diffuse shading
float diff = max(dot(normal, lightDir), 0.0); float diff = max(dot(normal, lightDir), 0.0);
@ -146,63 +176,53 @@ float calcLightIntensityTotal(vec3 normal){
// //
vec3 getTotalLightColor(vec3 normal){ vec3 getTotalLightColor(vec3 normal){
//get the direct light color adjusted for intensity //get the direct light color adjusted for intensity
vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal); vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
//sum light colors //sum light colors
vec3 totalLightColor = diffuseLightColor; vec3 totalLightColor = diffuseLightColor;
return totalLightColor; return totalLightColor;
} }
vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){ vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
vec3 lightDir = normalize(pLposition[i] - fragPos); vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
// diffuse shading // diffuse shading
float diff = max(dot(normal, lightDir), 0.0); float diff = max(dot(normal, lightDir), 0.0);
// specular shading // specular shading
// vec3 reflectDir = reflect(-lightDir, normal); // vec3 reflectDir = reflect(-lightDir, normal);
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation // attenuation
float distance = length(pLposition[i] - fragPos); float distance = length(pointLight.position.xyz - fragPos);
float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance)); float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
if(distance > pointLight.radius){
attenuation = 0;
}
// combine results // combine results
vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz; vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
vec3 diffuse = pLdiffuse[i] * diff;// * 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; // vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
ambient *= attenuation; ambient = ambient * attenuation;
diffuse *= attenuation; diffuse = diffuse * attenuation;
// specular *= attenuation; // specular *= attenuation;
vec3 specular = vec3(0,0,0); vec3 specular = vec3(0,0,0);
vec3 finalValue = (ambient + diffuse + specular); vec3 finalValue = vec3(0);
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,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; return finalValue;
} }
// // calculates the color when using a point light. /**
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){ Finds the light cluster this fragment belongs to
// vec3 lightDir = normalize(pLposition[i] - fragPos); */
// // diffuse shading uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
// float diff = max(dot(normal, lightDir), 0.0); uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
// // specular shading vec2 tileSize = screenDimensions / gridSize.xy;
// // vec3 reflectDir = reflect(-lightDir, normal); uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
// // 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){ float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){

View File

@ -30,6 +30,7 @@ uniform int numBones;
//output buffers //output buffers
out vec3 Normal; out vec3 Normal;
out vec3 FragPos; out vec3 FragPos;
out vec3 ViewFragPos;
out vec2 TexCoord; out vec2 TexCoord;
out vec4 FragPosLightSpace; out vec4 FragPosLightSpace;
@ -59,6 +60,7 @@ void main() {
//push frag, normal, and texture positions to fragment shader //push frag, normal, and texture positions to fragment shader
FragPos = vec3(model * FinalVertex); FragPos = vec3(model * FinalVertex);
ViewFragPos = vec3(view * model * FinalVertex);
Normal = mat3(transpose(inverse(model))) * FinalNormal.xyz; Normal = mat3(transpose(inverse(model))) * FinalNormal.xyz;
TexCoord = aTex; TexCoord = aTex;

View File

@ -0,0 +1,97 @@
#version 450 core
/**
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
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
struct Cluster {
vec4 minPoint;
vec4 maxPoint;
uint count;
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
};
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterSSBO {
Cluster clusters[];
};
uniform float zNear;
uniform float zFar;
uniform mat4 inverseProjection;
uniform uvec3 gridSize;
uniform uvec2 screenDimensions;
vec3 screenToView(vec2 screenCoord);
vec3 lineIntersectionWithZPlane(vec3 startPoint, vec3 endPoint, float zDistance);
/*
context: glViewport is referred to as the "screen"
clusters are built based on a 2d screen-space grid and depth slices.
Later when shading, it is easy to figure what cluster a fragment is in based on
gl_FragCoord.xy and the fragment's z depth from camera
*/
void main() {
uint tileIndex = gl_WorkGroupID.x + (gl_WorkGroupID.y * gridSize.x) +
(gl_WorkGroupID.z * gridSize.x * gridSize.y);
vec2 tileSize = screenDimensions / gridSize.xy;
// tile in screen-space
vec2 minTile_screenspace = gl_WorkGroupID.xy * tileSize;
vec2 maxTile_screenspace = (gl_WorkGroupID.xy + 1) * tileSize;
// convert tile to view space sitting on the near plane
vec3 minTile = screenToView(minTile_screenspace);
vec3 maxTile = screenToView(maxTile_screenspace);
float planeNear =
zNear * pow(zFar / zNear, gl_WorkGroupID.z / float(gridSize.z));
float planeFar =
zNear * pow(zFar / zNear, (gl_WorkGroupID.z + 1) / float(gridSize.z));
// the line goes from the eye position in view space (0, 0, 0)
// through the min/max points of a tile to intersect with a given cluster's near-far planes
vec3 minPointNear =
lineIntersectionWithZPlane(vec3(0, 0, 0), minTile, planeNear);
vec3 minPointFar =
lineIntersectionWithZPlane(vec3(0, 0, 0), minTile, planeFar);
vec3 maxPointNear =
lineIntersectionWithZPlane(vec3(0, 0, 0), maxTile, planeNear);
vec3 maxPointFar =
lineIntersectionWithZPlane(vec3(0, 0, 0), maxTile, planeFar);
clusters[tileIndex].minPoint = vec4(min(minPointNear, minPointFar), 0.0);
clusters[tileIndex].maxPoint = vec4(max(maxPointNear, maxPointFar), 0.0);
}
// Returns the intersection point of an infinite line and a
// plane perpendicular to the Z-axis
vec3 lineIntersectionWithZPlane(vec3 startPoint, vec3 endPoint, float zDistance) {
vec3 direction = endPoint - startPoint;
vec3 normal = vec3(0.0, 0.0, -1.0); // plane normal
// skip check if the line is parallel to the plane.
float t = (zDistance - dot(normal, startPoint)) / dot(normal, direction);
return startPoint + t * direction; // the parametric form of the line equation
}
vec3 screenToView(vec2 screenCoord) {
// normalize screenCoord to [-1, 1] and
// set the NDC depth of the coordinate to be on the near plane. This is -1 by
// default in OpenGL
vec4 ndc = vec4(screenCoord / screenDimensions * 2.0 - 1.0, -1.0, 1.0);
vec4 viewCoord = inverseProjection * ndc;
viewCoord /= viewCoord.w;
return viewCoord.xyz;
}

View File

@ -0,0 +1,87 @@
#version 450 core
/**
Maximum number of lights per cluster
*/
#define MAX_LIGHTS_PER_CLUSTER 100
/**
The number of "threads" to run
*/
#define CULL_LOCAL_SIZE 128
/**
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
layout(local_size_x = CULL_LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in;
struct PointLight {
vec4 position;
vec4 color;
float constant;
float linear;
float quadratic;
float radius;
};
struct Cluster {
vec4 minPoint;
vec4 maxPoint;
uint count;
uint lightIndices[MAX_LIGHTS_PER_CLUSTER];
};
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterSSBO {
Cluster clusters[];
};
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer lightSSBO {
PointLight pointLight[];
};
uniform mat4 viewMatrix;
bool testSphereAABB(uint i, Cluster c);
// each invocation of main() is a thread processing a cluster
void main() {
uint lightCount = pointLight.length();
uint index = gl_WorkGroupID.x * CULL_LOCAL_SIZE + gl_LocalInvocationID.x;
Cluster cluster = clusters[index];
// we need to reset count because culling runs every frame.
// otherwise it would accumulate.
cluster.count = 0;
for (uint i = 0; i < lightCount; ++i){
if (testSphereAABB(i, cluster) && cluster.count < 100){
cluster.lightIndices[cluster.count] = i;
cluster.count++;
}
}
clusters[index] = cluster;
}
bool sphereAABBIntersection(vec3 center, float radius, vec3 aabbMin, vec3 aabbMax) {
// closest point on the AABB to the sphere center
vec3 closestPoint = clamp(center, aabbMin, aabbMax);
// squared distance between the sphere center and closest point
float distanceSquared = dot(closestPoint - center, closestPoint - center);
return distanceSquared <= radius * radius;
}
// this just unpacks data for sphereAABBIntersection
bool testSphereAABB(uint i, Cluster cluster) {
vec3 center = vec3(viewMatrix * pointLight[i].position);
float radius = pointLight[i].radius;
vec3 aabbMin = cluster.minPoint.xyz;
vec3 aabbMax = cluster.maxPoint.xyz;
return sphereAABBIntersection(center, radius, aabbMin, aabbMax);
}

View File

@ -1,36 +1,67 @@
#version 400 core #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];
};
#define NR_POINT_LIGHTS 10
layout (location = 0) out vec4 accum; layout (location = 0) out vec4 accum;
layout (location = 1) out float reveal; layout (location = 1) out float reveal;
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
Cluster clusters[];
};
layout (std140) uniform Lights { layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
// this is how many because we have to align PointLight pointLight[];
// 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
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
DirectLight directLight;
}; };
struct Material { struct Material {
@ -42,6 +73,7 @@ struct Material {
//inputs //inputs
in vec3 FragPos; in vec3 FragPos;
in vec3 ViewFragPos;
in vec3 Normal; in vec3 Normal;
in vec2 TexCoord; in vec2 TexCoord;
in vec4 FragPosLightSpace; in vec4 FragPosLightSpace;
@ -58,9 +90,20 @@ uniform Material material;
//light depth map //light depth map
uniform sampler2D shadowMap; 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 //function prototypes
float calcLightIntensityTotal(vec3 normal); 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 ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
float linearizeDepth(float d,float zNear,float zFar); float linearizeDepth(float d,float zNear,float zFar);
float weightCalcOrigin(float finalAlpha, float zLoc, float linearizedLoc); float weightCalcOrigin(float finalAlpha, float zLoc, float linearizedLoc);
@ -74,17 +117,33 @@ void main(){
vec3 viewDir = normalize(viewPos - FragPos); vec3 viewDir = normalize(viewPos - FragPos);
//grab light intensity //grab light intensity
float lightIntensity = calcLightIntensityTotal(norm); vec3 lightIntensity = vec3(calcLightIntensityTotal(norm));
//get color of base texture //get color of base texture
vec4 textureColor = texture(material.diffuse, TexCoord); vec4 textureColor = texture(material.diffuse, TexCoord);
vec3 textureRGB = textureColor.rgb; vec3 textureRGB = textureColor.rgb;
//shadow //shadow
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-dLDirection), norm); float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), norm);
vec3 shadowModifiedColor = textureRGB * lightIntensity * max(shadow, 0.4);
//
//point light calculations
uint clusterIndex = findCluster(ViewFragPos, zNear, zFar);
uint pointLightCount = clusters[clusterIndex].count;
for(int i = 0; i < pointLightCount; i++){
uint pointLightIndex = clusters[clusterIndex].lightIndices[i];
PointLight pointLight = pointLight[pointLightIndex];
lightIntensity = lightIntensity + CalcPointLight(pointLight, norm, FragPos, viewDir);
}
//error checking on light clusters
if(pointLightCount > MAX_LIGHTS_PER_CLUSTER){
accum = vec4(1.0f,0.0f,0.0f,1);
reveal = textureColor.a;
return;
}
//calculate final color //calculate final color
vec3 shadowModifiedColor = textureRGB * lightIntensity * max(shadow, 0.4);
vec4 finalColor = vec4(shadowModifiedColor,textureColor.a); vec4 finalColor = vec4(shadowModifiedColor,textureColor.a);
//calculate weight function //calculate weight function
@ -127,13 +186,13 @@ float linearizeDepth(float d,float zNear,float zFar){
float calcLightIntensityAmbient(){ float calcLightIntensityAmbient(){
//calculate average of ambient light //calculate average of ambient light
float avg = (dLAmbient.x + dLAmbient.y + dLAmbient.z)/3.0; float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
return avg; return avg;
} }
// //
float calcLightIntensityDir(vec3 normal){ float calcLightIntensityDir(vec3 normal){
vec3 lightDir = normalize(-dLDirection); vec3 lightDir = normalize(-directLight.direction);
// diffuse shading // diffuse shading
float diff = max(dot(normal, lightDir), 0.0); float diff = max(dot(normal, lightDir), 0.0);
@ -156,38 +215,55 @@ float calcLightIntensityTotal(vec3 normal){
// //
vec3 getTotalLightColor(vec3 normal){ vec3 getTotalLightColor(vec3 normal){
//get the direct light color adjusted for intensity //get the direct light color adjusted for intensity
vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal); vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
//sum light colors //sum light colors
vec3 totalLightColor = diffuseLightColor; vec3 totalLightColor = diffuseLightColor;
return totalLightColor; return totalLightColor;
} }
vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){
vec3 lightDir = normalize(pLposition[i] - fragPos); vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
// diffuse shading // diffuse shading
float diff = max(dot(normal, lightDir), 0.0); float diff = max(dot(normal, lightDir), 0.0);
// specular shading // specular shading
// vec3 reflectDir = reflect(-lightDir, normal); // vec3 reflectDir = reflect(-lightDir, normal);
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation // attenuation
float distance = length(pLposition[i] - fragPos); float distance = length(pointLight.position.xyz - fragPos);
float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance)); float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
if(distance > pointLight.radius){
attenuation = 0;
}
// combine results // combine results
vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz; vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
vec3 diffuse = pLdiffuse[i] * diff;// * 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; // vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
ambient *= attenuation; ambient = ambient * attenuation;
diffuse *= attenuation; diffuse = diffuse * attenuation;
// specular *= attenuation; // specular *= attenuation;
vec3 specular = vec3(0,0,0); vec3 specular = vec3(0,0,0);
vec3 finalValue = (ambient + diffuse + specular); vec3 finalValue = vec3(0);
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,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; 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);
}

View File

@ -30,6 +30,7 @@ uniform int numBones;
//output buffers //output buffers
out vec3 Normal; out vec3 Normal;
out vec3 FragPos; out vec3 FragPos;
out vec3 ViewFragPos;
out vec2 TexCoord; out vec2 TexCoord;
out vec4 FragPosLightSpace; out vec4 FragPosLightSpace;
@ -59,6 +60,7 @@ void main() {
//push frag, normal, and texture positions to fragment shader //push frag, normal, and texture positions to fragment shader
FragPos = vec3(model * FinalVertex); FragPos = vec3(model * FinalVertex);
ViewFragPos = vec3(view * model * FinalVertex);
Normal = mat3(transpose(inverse(model))) * FinalNormal.xyz; Normal = mat3(transpose(inverse(model))) * FinalNormal.xyz;
TexCoord = aTex; TexCoord = aTex;

View File

@ -1,37 +1,68 @@
#version 330 core #version 450 core
//foliage.fs //foliage.fs
#define NR_POINT_LIGHTS 10 /**
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; out vec4 FragColor;
layout (std140) uniform Lights { layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
// this is how many because we have to align Cluster clusters[];
// 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 layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
vec3 pLposition[NR_POINT_LIGHTS]; // 16*10 64 PointLight pointLight[];
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
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
DirectLight directLight;
}; };
struct Material { struct Material {
@ -41,6 +72,7 @@ struct Material {
}; };
in vec3 FragPos; in vec3 FragPos;
in vec3 ViewFragPos;
in vec3 Normal; in vec3 Normal;
in vec2 TexCoord; in vec2 TexCoord;
in vec4 FragPosLightSpace; in vec4 FragPosLightSpace;
@ -62,11 +94,19 @@ uniform int hasTransparency;
//light depth map //light depth map
uniform sampler2D shadowMap; 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 // function prototypes
// vec3 CalcDirLight(vec3 normal, vec3 viewDir); uint findCluster(vec3 FragPos, float zNear, float zFar);
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir); vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
// vec3 CalcSpotLight(vec3 normal, vec3 fragPos, vec3 viewDir);
float calcLightIntensityTotal(vec3 normal); float calcLightIntensityTotal(vec3 normal);
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal); float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
float easeIn(float interpolator); float easeIn(float interpolator);
@ -90,7 +130,7 @@ void main(){
vec3 viewDir = normalize(viewPos - FragPos); vec3 viewDir = normalize(viewPos - FragPos);
//grab light intensity //grab light intensity
float lightIntensity = calcLightIntensityTotal(norm); vec3 lightIntensity = vec3(calcLightIntensityTotal(norm));
//get color of base texture //get color of base texture
// vec3 textureColor = vec3((norm.x + 1) / 2.0, norm.y, 1.0 - (norm.x + 1) / 2.0); // vec3 textureColor = vec3((norm.x + 1) / 2.0, norm.y, 1.0 - (norm.x + 1) / 2.0);
@ -98,7 +138,22 @@ void main(){
// vec3 textureColor = vec3(0.17647,0.4,0.09411);//texture(material.diffuse, TexCoord).rgb; // vec3 textureColor = vec3(0.17647,0.4,0.09411);//texture(material.diffuse, TexCoord).rgb;
//shadow //shadow
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-dLDirection), norm); float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), norm);
//
//point light calculations
uint clusterIndex = findCluster(ViewFragPos, zNear, zFar);
uint pointLightCount = clusters[clusterIndex].count;
for(int i = 0; i < pointLightCount; i++){
uint pointLightIndex = clusters[clusterIndex].lightIndices[i];
PointLight pointLight = pointLight[pointLightIndex];
lightIntensity = lightIntensity + CalcPointLight(pointLight, norm, FragPos, viewDir);
}
//error checking on light clusters
if(pointLightCount > MAX_LIGHTS_PER_CLUSTER){
FragColor = vec4(1.0f,0.0f,0.0f,1);
return;
}
//calculate final color //calculate final color
vec3 finalColor = textureColor * lightIntensity;// * max(shadow,0.4); vec3 finalColor = textureColor * lightIntensity;// * max(shadow,0.4);
@ -133,13 +188,13 @@ void main(){
// //
float calcLightIntensityAmbient(){ float calcLightIntensityAmbient(){
//calculate average of ambient light //calculate average of ambient light
float avg = (dLAmbient.x + dLAmbient.y + dLAmbient.z)/3.0; float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
return avg; return avg;
} }
// //
float calcLightIntensityDir(vec3 normal){ float calcLightIntensityDir(vec3 normal){
vec3 lightDir = normalize(-dLDirection); vec3 lightDir = normalize(-directLight.direction);
// diffuse shading // diffuse shading
float diff = max(dot(normal, lightDir), 0.0); float diff = max(dot(normal, lightDir), 0.0);
@ -162,64 +217,53 @@ float calcLightIntensityTotal(vec3 normal){
// //
vec3 getTotalLightColor(vec3 normal){ vec3 getTotalLightColor(vec3 normal){
//get the direct light color adjusted for intensity //get the direct light color adjusted for intensity
vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal); vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
//sum light colors //sum light colors
vec3 totalLightColor = diffuseLightColor; vec3 totalLightColor = diffuseLightColor;
return totalLightColor; return totalLightColor;
} }
vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){ vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
vec3 lightDir = normalize(pLposition[i] - fragPos); vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
// diffuse shading // diffuse shading
float diff = max(dot(normal, lightDir), 0.0); float diff = max(dot(normal, lightDir), 0.0);
// specular shading // specular shading
// vec3 reflectDir = reflect(-lightDir, normal); // vec3 reflectDir = reflect(-lightDir, normal);
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation // attenuation
float distance = length(pLposition[i] - fragPos); float distance = length(pointLight.position.xyz - fragPos);
float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance)); float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
if(distance > pointLight.radius){
attenuation = 0;
}
// combine results // combine results
vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz; vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
vec3 diffuse = pLdiffuse[i] * diff;// * 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; // vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
ambient *= attenuation; ambient = ambient * attenuation;
diffuse *= attenuation; diffuse = diffuse * attenuation;
// specular *= attenuation; // specular *= attenuation;
vec3 specular = vec3(0,0,0); vec3 specular = vec3(0,0,0);
vec3 finalValue = (ambient + diffuse + specular); vec3 finalValue = vec3(0);
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,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; return finalValue;
} }
// // calculates the color when using a point light. /**
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){ Finds the light cluster this fragment belongs to
// vec3 lightDir = normalize(pLposition[i] - fragPos); */
// // diffuse shading uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
// float diff = max(dot(normal, lightDir), 0.0); uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
// // specular shading vec2 tileSize = screenDimensions / gridSize.xy;
// // vec3 reflectDir = reflect(-lightDir, normal); uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
// // 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){ float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){

View File

@ -40,6 +40,7 @@ uniform float time;
//output buffers //output buffers
out vec3 Normal; out vec3 Normal;
out vec3 FragPos; out vec3 FragPos;
out vec3 ViewFragPos;
out vec2 TexCoord; out vec2 TexCoord;
out vec4 FragPosLightSpace; out vec4 FragPosLightSpace;
out vec3 normalRot1; out vec3 normalRot1;
@ -156,6 +157,7 @@ void main() {
//push frag, normal, and texture positions to fragment shader //push frag, normal, and texture positions to fragment shader
// //
FragPos = vec3(FinalVertex); FragPos = vec3(FinalVertex);
ViewFragPos = vec3(view * model * FinalVertex);
Normal = vec3(FinalNormal); Normal = vec3(FinalNormal);
TexCoord = aTex; TexCoord = aTex;

View File

@ -1,4 +1,4 @@
#version 330 core #version 450 core
//texture defines //texture defines
#define ATLAS_ELEMENT_DIM 256.0 #define ATLAS_ELEMENT_DIM 256.0
@ -8,37 +8,67 @@
#define ATLAS_NORMALIZED_ELEMENT_WIDTH_FULL 0.03125 //used to properly shift from texture to texture in the atlas #define ATLAS_NORMALIZED_ELEMENT_WIDTH_FULL 0.03125 //used to properly shift from texture to texture in the atlas
#define NR_POINT_LIGHTS 10 /**
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; out vec4 FragColor;
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
Cluster clusters[];
};
layout (std140) uniform Lights { layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
// this is how many because we have to align PointLight pointLight[];
// 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
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
DirectLight directLight;
}; };
struct Material { struct Material {
@ -48,6 +78,7 @@ struct Material {
}; };
in vec3 FragPos; in vec3 FragPos;
in vec3 ViewFragPos;
in vec3 Normal; in vec3 Normal;
in vec2 texPlane1; in vec2 texPlane1;
in vec2 texPlane2; in vec2 texPlane2;
@ -71,11 +102,19 @@ uniform int hasTransparency;
//light depth map //light depth map
uniform sampler2D shadowMap; 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 // function prototypes
// vec3 CalcDirLight(vec3 normal, vec3 viewDir); uint findCluster(vec3 FragPos, float zNear, float zFar);
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir); vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
// vec3 CalcSpotLight(vec3 normal, vec3 fragPos, vec3 viewDir);
float calcLightIntensityTotal(vec3 normal); float calcLightIntensityTotal(vec3 normal);
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, 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); vec3 getColor(vec2 texPlane1, vec2 texPlane2, vec2 texPlane3, vec3 normal, vec3 samplerIndexVec, vec3 samplerRatioVec, Material material);
@ -85,20 +124,31 @@ void main(){
vec3 viewDir = normalize(viewPos - FragPos); vec3 viewDir = normalize(viewPos - FragPos);
//grab light intensity //grab light intensity
float lightIntensity = calcLightIntensityTotal(norm); vec3 lightIntensity = vec3(calcLightIntensityTotal(norm));
//get color of base texture //get color of base texture
vec3 textureColor = getColor(texPlane1, texPlane2, texPlane3, norm, samplerIndexVec, samplerRatioVec, material); vec3 textureColor = getColor(texPlane1, texPlane2, texPlane3, norm, samplerIndexVec, samplerRatioVec, material);
//shadow //shadow
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-dLDirection), norm); float shadow = ShadowCalculation(FragPosLightSpace, normalize(-directLight.direction), norm);
//
//point light calculations
uint clusterIndex = findCluster(ViewFragPos, zNear, zFar);
uint pointLightCount = clusters[clusterIndex].count;
for(int i = 0; i < pointLightCount; i++){
uint pointLightIndex = clusters[clusterIndex].lightIndices[i];
PointLight pointLight = pointLight[pointLightIndex];
lightIntensity = lightIntensity + CalcPointLight(pointLight, norm, FragPos, viewDir);
}
//error checking on light clusters
if(pointLightCount > MAX_LIGHTS_PER_CLUSTER){
FragColor = vec4(1.0f,0.0f,0.0f,1);
return;
}
//calculate final color //calculate final color
vec3 finalColor = textureColor * lightIntensity * max(shadow,0.4); vec3 finalColor = textureColor * lightIntensity * max(shadow,0.4);
// 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 //this final calculation is for transparency
FragColor = vec4(finalColor, 1); FragColor = vec4(finalColor, 1);
@ -188,13 +238,13 @@ vec3 getColor(vec2 texPlane1, vec2 texPlane2, vec2 texPlane3, vec3 normal, vec3
// //
float calcLightIntensityAmbient(){ float calcLightIntensityAmbient(){
//calculate average of ambient light //calculate average of ambient light
float avg = (dLAmbient.x + dLAmbient.y + dLAmbient.z)/3.0; float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
return avg; return avg;
} }
// //
float calcLightIntensityDir(vec3 normal){ float calcLightIntensityDir(vec3 normal){
vec3 lightDir = normalize(-dLDirection); vec3 lightDir = normalize(-directLight.direction);
// diffuse shading // diffuse shading
float diff = max(dot(normal, lightDir), 0.0); float diff = max(dot(normal, lightDir), 0.0);
@ -217,37 +267,54 @@ float calcLightIntensityTotal(vec3 normal){
// //
vec3 getTotalLightColor(vec3 normal){ vec3 getTotalLightColor(vec3 normal){
//get the direct light color adjusted for intensity //get the direct light color adjusted for intensity
vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal); vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
//sum light colors //sum light colors
vec3 totalLightColor = diffuseLightColor; vec3 totalLightColor = diffuseLightColor;
return totalLightColor; return totalLightColor;
} }
vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){ vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
vec3 lightDir = normalize(pLposition[i] - fragPos); vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
// diffuse shading // diffuse shading
float diff = max(dot(normal, lightDir), 0.0); float diff = max(dot(normal, lightDir), 0.0);
// specular shading // specular shading
// vec3 reflectDir = reflect(-lightDir, normal); // vec3 reflectDir = reflect(-lightDir, normal);
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation // attenuation
float distance = length(pLposition[i] - fragPos); float distance = length(pointLight.position.xyz - fragPos);
float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance)); float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
if(distance > pointLight.radius){
attenuation = 0;
}
// combine results // combine results
vec3 ambient = pLambient[i]; vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
vec3 diffuse = pLdiffuse[i] * diff; vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
ambient *= attenuation; // vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
diffuse *= attenuation; ambient = ambient * attenuation;
diffuse = diffuse * attenuation;
// specular *= attenuation; // specular *= attenuation;
vec3 specular = vec3(0,0,0); vec3 specular = vec3(0,0,0);
vec3 finalValue = (ambient + diffuse + specular); vec3 finalValue = vec3(0);
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,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; 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){ float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){

View File

@ -26,6 +26,7 @@ uniform mat4 lightSpaceMatrix;
//output buffers //output buffers
out vec3 Normal; out vec3 Normal;
out vec3 FragPos; out vec3 FragPos;
out vec3 ViewFragPos;
out vec2 texPlane1; out vec2 texPlane1;
out vec2 texPlane2; out vec2 texPlane2;
out vec2 texPlane3; out vec2 texPlane3;
@ -44,6 +45,7 @@ void main() {
//push frag, normal, and texture positions to fragment shader //push frag, normal, and texture positions to fragment shader
FragPos = vec3(model * FinalVertex); FragPos = vec3(model * FinalVertex);
ViewFragPos = vec3(view * model * FinalVertex);
Normal = mat3(transpose(inverse(model))) * aNormal; Normal = mat3(transpose(inverse(model))) * aNormal;
//reference https://catlikecoding.com/unity/tutorials/advanced-rendering/triplanar-mapping/ //reference https://catlikecoding.com/unity/tutorials/advanced-rendering/triplanar-mapping/

View File

@ -1,3 +1,3 @@
#maven.buildNumber.plugin properties file #maven.buildNumber.plugin properties file
#Mon Sep 16 19:58:57 EDT 2024 #Wed Sep 18 20:37:06 EDT 2024
buildNumber=333 buildNumber=338

View File

@ -5,13 +5,21 @@ Design notes for the chemistry system
Ideas for the chemistry system: Ideas for the chemistry system:
- fire - fire
- Torch
- Fire Arrow
- water - water
- bucket
- electricity - electricity
- lightning arrow
- ice - ice
- ice chunk/block
- light
- Glittering chunk
- Wind/fans
- Placeable fan
- gravity - gravity
- stabilization - stabilization
- metal parts / conductivity - metal parts / conductivity
- light
- mirrors - mirrors
- plants burning - plants burning
- plants growing really fast - plants growing really fast
@ -20,6 +28,5 @@ Ideas for the chemistry system:
- spinning mechanisms and gears - spinning mechanisms and gears
- weighing things down and measuring scales w/ weight - weighing things down and measuring scales w/ weight
- trampolines - trampolines
- Wind/fans
- Weight - Weight
- Music - Music

View File

@ -37,6 +37,8 @@
- Spawn player in a town with a quest to complete a nearby dungeon - Spawn player in a town with a quest to complete a nearby dungeon
+ bug fixes + bug fixes
Fix light cluster mapping for foliage shader
Fix ui elements not storing default discrete world size on level editor menu
Fix skeleton right strafe Fix skeleton right strafe
Fix block tree preventing initiating an attack Fix block tree preventing initiating an attack
Fix return to title menu synchronization bug Fix return to title menu synchronization bug

View File

@ -801,6 +801,11 @@ Migrate documentation
Netcode generator qol fixes Netcode generator qol fixes
Combat Stances Component Combat Stances Component
Remove geometry shader support Remove geometry shader support
Work on clustered lighting
(09/19/2024)
Cluster lighting completed
# TODO # TODO
@ -836,11 +841,15 @@ Code Generation
Rearchitecting Rearchitecting
- Main render is a ui element (that we can have multiple of) - Main render is a ui element (that we can have multiple of)
- Shader handling updates to allow for library based shader compilation
- Also allow injecting consts from the engine itself (ie max lights is dynamically injected, that way never have to worry about .glsl and .java not aligning)
Code cleanup Code cleanup
- Rename "BehaviorTree" to be "Component" (what it actually is) - Rename "BehaviorTree" to be "Component" (what it actually is)
- Refactor ground movement components - Refactor ground movement components
- Refactor menu clases to be under electrosphere.client package - Refactor menu clases to be under electrosphere.client package
- Rename "ShaderProgram" to "VisualShader"
- Have ComputeShader and VisualShader use same static method for uploading uniforms
Goof off today requirements: Goof off today requirements:
Transvoxel implementation Transvoxel implementation

View File

@ -232,6 +232,24 @@ public class CameraEntityUtils {
return rVal; return rVal;
} }
/**
* Gets the near clip of the camera
* @param camera The camera
* @return The near clip
*/
public static float getNearClip(Entity camera){
return Globals.nearClip;
}
/**
* Gets the far clip of the camera
* @param camera The camera
* @return The far clip
*/
public static float getFarClip(Entity camera){
return Globals.userSettings.getGraphicsViewDistance();
}
/** /**
* Gets the rotation quaternion from a camera entity * Gets the rotation quaternion from a camera entity
* @param entity The entity * @param entity The entity

View File

@ -250,6 +250,7 @@ public class Globals {
public static float verticalFOV = 90; public static float verticalFOV = 90;
public static float aspectRatio = 2.0f; public static float aspectRatio = 2.0f;
public static float nearClip = 0.001f;
//matrices for drawing models //matrices for drawing models
public static Matrix4f viewMatrix = new Matrix4f(); public static Matrix4f viewMatrix = new Matrix4f();
@ -651,6 +652,10 @@ public class Globals {
assetManager.addShaderToQueue("Shaders/ui/debug/windowBorder/windowBound.vs", "Shaders/ui/debug/windowBorder/windowBound.fs"); assetManager.addShaderToQueue("Shaders/ui/debug/windowBorder/windowBound.vs", "Shaders/ui/debug/windowBorder/windowBound.fs");
assetManager.addShaderToQueue("Shaders/ui/debug/windowContentBorder/windowContentBound.vs", "Shaders/ui/debug/windowContentBorder/windowContentBound.fs"); assetManager.addShaderToQueue("Shaders/ui/debug/windowContentBorder/windowContentBound.vs", "Shaders/ui/debug/windowContentBorder/windowContentBound.fs");
//compute shaders
assetManager.addComputeShaderToQueue(AssetDataStrings.COMPUTE_LIGHT_CLUSTER);
assetManager.addComputeShaderToQueue(AssetDataStrings.COMPUTE_LIGHT_CULL);
//as these assets are required for the renderer to work, we go ahead and //as these assets are required for the renderer to work, we go ahead and
//load them into memory now. The loading time penalty is worth it I think. //load them into memory now. The loading time penalty is worth it I think.
Globals.assetManager.loadAssetsInQueue(); Globals.assetManager.loadAssetsInQueue();

View File

@ -45,4 +45,10 @@ public class AssetDataStrings {
public static final String UI_SFX_ITEM_GRAB = "Audio/ui/items/inventoryGrabItem.ogg"; public static final String UI_SFX_ITEM_GRAB = "Audio/ui/items/inventoryGrabItem.ogg";
public static final String UI_SFX_ITEM_RELEASE = "Audio/ui/items/inventorySlotItem.ogg"; public static final String UI_SFX_ITEM_RELEASE = "Audio/ui/items/inventorySlotItem.ogg";
/**
* Compute shaders
*/
public static final String COMPUTE_LIGHT_CLUSTER = "Shaders/core/light/cluster.comp";
public static final String COMPUTE_LIGHT_CULL = "Shaders/core/light/cull.comp";
} }

View File

@ -13,6 +13,7 @@ import electrosphere.renderer.buffer.HomogenousUniformBuffer;
import electrosphere.renderer.loading.ModelLoader; import electrosphere.renderer.loading.ModelLoader;
import electrosphere.renderer.model.Mesh; import electrosphere.renderer.model.Mesh;
import electrosphere.renderer.model.Model; import electrosphere.renderer.model.Model;
import electrosphere.renderer.shader.ComputeShader;
import electrosphere.renderer.shader.ShaderProgram; import electrosphere.renderer.shader.ShaderProgram;
import electrosphere.renderer.texture.Texture; import electrosphere.renderer.texture.Texture;
import electrosphere.renderer.texture.TextureMap; import electrosphere.renderer.texture.TextureMap;
@ -20,6 +21,7 @@ import electrosphere.server.poseactor.PoseModel;
import electrosphere.util.FileUtils; import electrosphere.util.FileUtils;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
@ -51,6 +53,12 @@ public class AssetManager {
Map<String,ShaderProgram> shadersLoadedIntoMemory = new ConcurrentHashMap<String,ShaderProgram>(); Map<String,ShaderProgram> shadersLoadedIntoMemory = new ConcurrentHashMap<String,ShaderProgram>();
List<ActorShaderMask> shadersInQueue = new CopyOnWriteArrayList<ActorShaderMask>(); List<ActorShaderMask> shadersInQueue = new CopyOnWriteArrayList<ActorShaderMask>();
//
//Compute shader related
//
Map<String,ComputeShader> computeShadersLoadedIntoMemory = new ConcurrentHashMap<String,ComputeShader>();
List<String> computeShadersInQueue = new CopyOnWriteArrayList<String>();
Map<String,DBody> physicsMeshesLoadedIntoMemory = new ConcurrentHashMap<String,DBody>(); Map<String,DBody> physicsMeshesLoadedIntoMemory = new ConcurrentHashMap<String,DBody>();
List<PhysicsMeshQueueItem> physicsMeshesToLoad = new CopyOnWriteArrayList<PhysicsMeshQueueItem>(); List<PhysicsMeshQueueItem> physicsMeshesToLoad = new CopyOnWriteArrayList<PhysicsMeshQueueItem>();
@ -126,6 +134,20 @@ public class AssetManager {
ShaderProgram.loadSpecificShader(currentShader.getVertexShaderPath(),currentShader.getFragmentShaderPath()) ShaderProgram.loadSpecificShader(currentShader.getVertexShaderPath(),currentShader.getFragmentShaderPath())
); );
} }
//compute shaders
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load compute shaders");
for(String computePath : computeShadersInQueue){
computeShadersInQueue.remove(computePath);
String key = getComputeShaderKey(computePath);
try {
computeShadersLoadedIntoMemory.put(
key,
ComputeShader.create(FileUtils.getAssetFileAsString(computePath))
);
} catch (IOException e) {
e.printStackTrace();
}
}
//pose models //pose models
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load pose models"); LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load pose models");
for(String currentPath: poseModelsInQueue){ for(String currentPath: poseModelsInQueue){
@ -416,6 +438,40 @@ public class AssetManager {
shadersLoadedIntoMemory.clear(); shadersLoadedIntoMemory.clear();
} }
//
//SHADERS
//
/**
* Adds a compute shader to the queue to be loaded
* @param computePath The path to the source code for the shader
*/
public void addComputeShaderToQueue(String computePath){
computeShadersInQueue.add(getComputeShaderKey(computePath));
}
/**
* Gets a compute shader
* @param computePath The path to the source code for the compute shader
* @return The compute shader if it exists, null otherwise
*/
public ComputeShader fetchComputeShader(String computePath){
String key = getComputeShaderKey(computePath);
ComputeShader rVal = null;
if(computeShadersLoadedIntoMemory.containsKey(key)){
rVal = computeShadersLoadedIntoMemory.get(key);
}
return rVal;
}
/**
* Gets the key for a compute shader
* @param computePath The path to the shader source
* @return The key
*/
static String getComputeShaderKey(String computePath){
return computePath;
}

View File

@ -9,6 +9,7 @@ import org.lwjgl.opengl.GL45;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.buffer.OpenGLBuffer;
import electrosphere.renderer.buffer.UniformBlockBinding; import electrosphere.renderer.buffer.UniformBlockBinding;
import electrosphere.renderer.shader.Shader; import electrosphere.renderer.shader.Shader;
import electrosphere.renderer.shader.ShaderProgram; import electrosphere.renderer.shader.ShaderProgram;
@ -122,7 +123,7 @@ public class OpenGLState {
* @return The viewport's dimensions * @return The viewport's dimensions
*/ */
public Vector2i getViewport(){ public Vector2i getViewport(){
return viewport; return new Vector2i(viewport);
} }
/** /**
@ -333,13 +334,13 @@ public class OpenGLState {
if(currentBuffer == null || currentBuffer != buffer){ if(currentBuffer == null || currentBuffer != buffer){
//does not already contain index, should bind //does not already contain index, should bind
this.indexBlockMap.put(index,buffer); this.indexBlockMap.put(index,buffer);
GL45.glBindBufferBase(index, index, buffer.getId()); GL45.glBindBufferBase(OpenGLBuffer.getTypeInt(buffer), index, buffer.getId());
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
} }
} else { } else {
//does not already contain index, should bind //does not already contain index, should bind
this.indexBlockMap.put(index,buffer); this.indexBlockMap.put(index,buffer);
GL45.glBindBufferBase(index, index, buffer.getId()); GL45.glBindBufferBase(OpenGLBuffer.getTypeInt(buffer), index, buffer.getId());
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
} }
} }
@ -348,10 +349,10 @@ public class OpenGLState {
* Unbinds a buffer from a given uniform buffer block index * Unbinds a buffer from a given uniform buffer block index
* @param index the index * @param index the index
*/ */
public void glUnbindBufferBase(int index){ public void glUnbindBufferBase(int index, UniformBlockBinding buffer){
if(this.indexBlockMap.containsKey(index)){ if(this.indexBlockMap.containsKey(index)){
this.indexBlockMap.remove(index); this.indexBlockMap.remove(index);
GL45.glBindBufferBase(index, index, UniformBlockBinding.UNBIND_ADDRESS); GL45.glBindBufferBase(OpenGLBuffer.getTypeInt(buffer), index, UniformBlockBinding.UNBIND_ADDRESS);
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
} }
} }

View File

@ -415,7 +415,7 @@ public class RenderingEngine {
//instantiate light manager //instantiate light manager
lightManager = new LightManager(); lightManager = LightManager.create();
// //
//Fog //Fog
@ -452,8 +452,7 @@ public class RenderingEngine {
verticalFOV = (float)(Globals.verticalFOV * Math.PI /180.0f); verticalFOV = (float)(Globals.verticalFOV * Math.PI /180.0f);
//set local aspect ratio and global aspect ratio at the same time //set local aspect ratio and global aspect ratio at the same time
aspectRatio = Globals.aspectRatio = Globals.WINDOW_WIDTH / (float)Globals.WINDOW_HEIGHT; aspectRatio = Globals.aspectRatio = Globals.WINDOW_WIDTH / (float)Globals.WINDOW_HEIGHT;
float nearClip = 0.001f; Globals.projectionMatrix.setPerspective(verticalFOV, Globals.aspectRatio, Globals.nearClip, Globals.userSettings.getGraphicsViewDistance());
Globals.projectionMatrix.setPerspective(verticalFOV, Globals.aspectRatio, nearClip, Globals.userSettings.getGraphicsViewDistance());
Globals.viewMatrix.translation(new Vector3f(0.0f,0.0f,-3.0f)); Globals.viewMatrix.translation(new Vector3f(0.0f,0.0f,-3.0f));
/** /**
@ -489,7 +488,7 @@ public class RenderingEngine {
} }
//Update light buffer //Update light buffer
lightManager.updateData(); lightManager.update(renderPipelineState,openGLState,Globals.playerCamera);
checkError(); checkError();

View File

@ -223,7 +223,7 @@ public class StridedInstanceData implements InstanceData {
@Override @Override
public void upload(OpenGLState openGLState, RenderPipelineState renderPipelineState){ public void upload(OpenGLState openGLState, RenderPipelineState renderPipelineState){
this.buffer.upload(); this.buffer.upload(openGLState);
openGLState.glBindBufferBase(0, buffer); openGLState.glBindBufferBase(0, buffer);
} }

View File

@ -4,9 +4,9 @@ import java.nio.ByteBuffer;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45;
import org.lwjgl.system.MemoryUtil;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.buffer.BufferEnums.BufferAccess; import electrosphere.renderer.buffer.BufferEnums.BufferAccess;
import electrosphere.renderer.buffer.BufferEnums.BufferUsage; import electrosphere.renderer.buffer.BufferEnums.BufferUsage;
@ -40,7 +40,7 @@ public class ShaderStorageBuffer implements UniformBlockBinding {
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
GL45.glBindBuffer(GL45.GL_SHADER_STORAGE_BUFFER, id); GL45.glBindBuffer(GL45.GL_SHADER_STORAGE_BUFFER, id);
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
GL45.glBufferData(GL45.GL_SHADER_STORAGE_BUFFER, MemoryUtil.NULL, BufferEnums.getBufferUsage(usage, access)); GL45.glBufferData(GL45.GL_SHADER_STORAGE_BUFFER, buffer, BufferEnums.getBufferUsage(usage, access));
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
GL45.glBindBuffer(GL45.GL_SHADER_STORAGE_BUFFER,id); GL45.glBindBuffer(GL45.GL_SHADER_STORAGE_BUFFER,id);
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
@ -51,19 +51,21 @@ public class ShaderStorageBuffer implements UniformBlockBinding {
/** /**
* Uploads the java side buffer to opengl * Uploads the java side buffer to opengl
*/ */
public void upload(){ public void upload(OpenGLState openGLState){
long offset = 0; long offset = 0;
//bind if(buffer.limit() > buffer.position()){
GL45.glBindBuffer(GL45.GL_SHADER_STORAGE_BUFFER,id); //bind
Globals.renderingEngine.checkError(); openGLState.glBindBufferBase(0, this);
Globals.renderingEngine.checkError();
//upload //upload
GL45.glBufferSubData(GL45.GL_SHADER_STORAGE_BUFFER, offset, buffer); GL45.glBufferSubData(OpenGLBuffer.getTypeInt(this), offset, buffer);
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
//unbind //unbind
GL45.glBindBuffer(GL45.GL_SHADER_STORAGE_BUFFER,UNBIND_ADDRESS); openGLState.glUnbindBufferBase(0, this);
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
}
} }
/** /**

View File

@ -10,64 +10,34 @@ public class DirectionalLight {
//the direction of the light as a uniform vector //the direction of the light as a uniform vector
Vector3f direction; Vector3f direction;
//the ambient color //the color
Vector3f ambient; Vector3f color;
//the diffuse color
Vector3f diffuse;
//the specular color
Vector3f specular;
public void setDirection(Vector3f direction) { public void setDirection(Vector3f direction) {
this.direction = direction; this.direction = direction;
} }
public void setAmbient(Vector3f ambient) { public void setColor(Vector3f color) {
this.ambient = ambient; this.color = color;
}
public void setDiffuse(Vector3f diffuse) {
this.diffuse = diffuse;
}
public void setSpecular(Vector3f specular) {
this.specular = specular;
} }
public Vector3f getDirection() { public Vector3f getDirection() {
return direction; return direction;
} }
public Vector3f getAmbient() { public Vector3f getColor() {
return ambient; return color;
}
public Vector3f getDiffuse() {
return diffuse;
}
public Vector3f getSpecular() {
return specular;
} }
public DirectionalLight(Vector3f direction){ public DirectionalLight(Vector3f direction){
this.direction = direction; this.direction = direction;
ambient = new Vector3f(0.05f, 0.05f, 0.05f); color = new Vector3f(1.0f);
diffuse = new Vector3f(0.4f, 0.4f, 0.4f);
specular = new Vector3f(0.5f, 0.5f, 0.5f);
this.direction.normalize(); this.direction.normalize();
ambient.normalize();
diffuse.normalize();
specular.normalize();
} }
public DirectionalLight(Vector3f direction, Vector3f color){ public DirectionalLight(Vector3f direction, Vector3f color){
this.direction = direction; this.direction = direction;
ambient = new Vector3f( color.x * 0.05f, color.y * 0.05f, color.z * 0.05f); this.color = new Vector3f(color);
diffuse = new Vector3f( color.x * 0.4f, color.y * 0.4f, color.z * 0.4f);
specular = new Vector3f(color.x * 0.5f, color.y * 0.5f, color.z * 0.5f);
this.direction.normalize(); this.direction.normalize();
ambient.normalize();
diffuse.normalize();
specular.normalize();
} }
} }

View File

@ -1,300 +1,339 @@
package electrosphere.renderer.light; package electrosphere.renderer.light;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL31.GL_UNIFORM_BUFFER;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.joml.Matrix4d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.lwjgl.BufferUtils; import org.joml.Vector3i;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL31;
import electrosphere.client.entity.camera.CameraEntityUtils; import electrosphere.client.entity.camera.CameraEntityUtils;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.OpenGLState; import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderingEngine; import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.shader.ShaderProgram; import electrosphere.renderer.buffer.ShaderStorageBuffer;
import electrosphere.renderer.buffer.BufferEnums.BufferAccess;
import electrosphere.renderer.buffer.BufferEnums.BufferUsage;
import electrosphere.renderer.shader.ComputeShader;
import electrosphere.renderer.shader.MemoryBarrier;
import electrosphere.renderer.shader.MemoryBarrier.Barrier;
/** /**
* Manages the light sources in the engine * Manages the light sources in the engine
*/ */
public class LightManager { public class LightManager {
final static int BIND_POINT = 1; /**
final static int POINT_LIGHT_COUNT = 10; * Maximum number of lights per cluster
final static int BUFFER_SIZE = 1184; */
int uboIndex; static final int MAX_LIGHTS_PER_CLUSTER = 100;
ByteBuffer dataBuffer;
//sun position (For shadow maps) /**
Vector3f sunPosition = new Vector3f(0.2f,-1.0f,0.3f); * Size of the light cluster structure
*/
static final int CLUSTER_STRUCT_SIZE = 16 + 16 + 4 + (4 * MAX_LIGHTS_PER_CLUSTER);
//lights /**
DirectionalLight directionalLight; * The width of the light cluster grid's x dimension
PointLight[] pointLights; */
public static final int LIGHT_CLUSTER_WIDTH_X = 12;
/**
* The width of the light cluster grid's y dimension
*/
public static final int LIGHT_CLUSTER_WIDTH_Y = 12;
/**
* The width of the light cluster grid's z dimension
*/
public static final int LIGHT_CLUSTER_WIDTH_Z = 24;
public LightManager(){ /**
* The size of a single point light struct
*/
static final int POINT_LIGHT_STRUCT_SIZE = 16 + 16 + 4 + 4 + 4 + 4;
//create data buffer /**
dataBuffer = BufferUtils.createByteBuffer(BUFFER_SIZE); * The maximum number of point lights
*/
static final int MAX_POINT_LIGHTS = 2048;
uboIndex = glGenBuffers(); /**
glBindBuffer(GL_UNIFORM_BUFFER, uboIndex); * The size of the point light buffer
glBufferData(GL_UNIFORM_BUFFER, BUFFER_SIZE, GL_DYNAMIC_DRAW); // allocate 152 bytes of memory */
//set range to full size static final int POINT_LIGHT_BUFFER_SIZE = POINT_LIGHT_STRUCT_SIZE * MAX_POINT_LIGHTS;
int offset = 0;
GL30.glBindBufferRange(GL_UNIFORM_BUFFER, BIND_POINT, uboIndex, offset, BUFFER_SIZE);
//unbind
glBindBuffer(GL_UNIFORM_BUFFER, 0);
//create directional light /**
directionalLight = new DirectionalLight(new Vector3f(1,-1,0).normalize()); * The number of "threads" to run for light culling
directionalLight.setAmbient(new Vector3f(0.6f,0.6f,0.6f)); */
directionalLight.setDiffuse(new Vector3f(0.3f,0.3f,0.3f)); static final int CULL_LOCAL_SIZE = 128;
directionalLight.setDirection(sunPosition);
directionalLight.setSpecular(new Vector3f(0.0f,0.0f,0.0f));
pointLights = new PointLight[POINT_LIGHT_COUNT]; /**
for(int i = 0; i < POINT_LIGHT_COUNT; i++){ * The number of work groups to dispatch for the light culling phase
pointLights[i] = new PointLight(new Vector3f(0,0,0),new Vector3f(0,0,0)); * !!note!! DISPATCH_LOCAL_COUNT * CULL_LOCAL_SIZE must equal (LIGHT_CLUSTER_WIDTH_X * LIGHT_CLUSTER_WIDTH_Y * LIGHT_CLUSTER_WIDTH_Z)
*/
static final int DISPATCH_LOCAL_COUNT = 27;
/**
* Size of the direct light buffer
*/
static final int DIRECT_LIGHT_BUFFER_SIZE = 12 + 12;
/**
* Bind point for the cluster ssbo
*/
public static final int CLUSTER_SSBO_BIND_POINT = 1;
/**
* Bind point for the point light ssbo
*/
public static final int POINT_LIGHT_SSBO_BIND_POINT = 2;
/**
* Bind point for the direct light ssbo
*/
public static final int DIRECT_LIGHT_SSBO_BIND_POINT = 3;
/**
* The cluster grid ssbo
Light cluster struct:
{
vec4 minPoint; //16 bytes
vec4 maxPoint; //16 bytes
unsigned int count; //4 bytes
unsigned int lightIndices[MAX_LIGHTS_PER_CLUSTER]; //assuming MAX_LIGHTS_PER_CLUSTER is 100, 400 bytes
}
Totals to 436 bytes
*/
ShaderStorageBuffer clusterGridSSBO;
/**
* The map of all entities to point lights
*/
Map<Entity,PointLight> entityPointLightMap;
/**
* The buffer of all point light data
Point light struct:
{
vec4 position; //16 bytes
vec4 color; //16 bytes
float constant; //4 bytes
float linear; // 4 bytes
float quadratic; // 4 bytes
float radius; //4 bytes
} }
pointLights[0].setAmbient(new Vector3f(0.924500f, 0.369800f, 0.092450f));
pointLights[0].setConstant(1.0f);
pointLights[0].setDiffuse(new Vector3f(0.924500f, 0.369800f, 0.092450f));
pointLights[0].setLinear(0.7f);
pointLights[0].setPosition(new Vector3f(1.0f,0.05f,1.0f));
pointLights[0].setQuadratic(1.8f);
pointLights[0].setSpecular(new Vector3f(0.0f,0.0f,0.0f));
// pointLights[0].setAmbient(new Vector3f(0.924500f, 0.369800f, 0.092450f)); */
// pointLights[0].setConstant(1.0f); ShaderStorageBuffer pointLightSSBO;
// pointLights[0].setDiffuse(new Vector3f(0.924500f, 0.369800f, 0.092450f));
// pointLights[0].setLinear(0.09f);
// pointLights[0].setPosition(new Vector3f(1.0f,0.05f,1.0f));
// pointLights[0].setQuadratic(0.032f);
// pointLights[0].setSpecular(new Vector3f(0.0f,0.0f,0.0f));
/**
* The direct light ssbo
*
struct DirectLight {
vec3 direction; //12 bytes
vec3 color; //12 bytes
};
*/
ShaderStorageBuffer dirLightSSBO;
/**
* The directional light
*/
DirectionalLight directionalLight;
/**
/* * Constructor
Vector3f lightLoc = new Vector3f(0.2f,-1.0f,0.3f); */
float temp[] = new float[3]; private LightManager(){
temp[0] = lightLoc.x;
temp[1] = lightLoc.y;
temp[2] = lightLoc.z;
glUniform3fv(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "dirLight.direction"), temp);
temp[0] = 0.4f;
temp[1] = 0.4f;
temp[2] = 0.4f;
glUniform3fv(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "dirLight.ambient"), temp);
temp[0] = 0.3f;
temp[1] = 0.3f;
temp[2] = 0.3f;
glUniform3fv(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "dirLight.diffuse"), temp);
temp[0] = 0.1f;
temp[1] = 0.1f;
temp[2] = 0.1f;
glUniform3fv(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "dirLight.specular"), temp);
temp[0] = 32f;
*/
//glBufferData(GL_UNIFORM_BUFFER, <my_data>, GL_STATIC_DRAW);
}
//
//
// HIGHER ORDER OBJECT MANIPULATION
//
//
public void setPointLight(PointLight light, int index){
pointLights[index] = light;
} }
/** /**
* Gets the directional light for this light manager * Creates a light manager
* @return the directional light * @return The light manager
*/
public static LightManager create(){
LightManager rVal = new LightManager();
//
//create the cluster ssbo
rVal.clusterGridSSBO = new ShaderStorageBuffer(
CLUSTER_STRUCT_SIZE * LIGHT_CLUSTER_WIDTH_X * LIGHT_CLUSTER_WIDTH_Y * LIGHT_CLUSTER_WIDTH_Z,
BufferUsage.STATIC,
BufferAccess.COPY
);
//
//create pointlight structures
rVal.entityPointLightMap = new HashMap<Entity,PointLight>();
rVal.pointLightSSBO = new ShaderStorageBuffer(POINT_LIGHT_BUFFER_SIZE, BufferUsage.DYNAMIC, BufferAccess.DRAW);
//create a shit ton of point lights
Random rand = new Random(0);
for(int i = 0; i < 500; i++){
PointLight newLight = new PointLight(new Vector3f(rand.nextFloat(32),rand.nextFloat(),rand.nextFloat(32)));
newLight.setRadius(1);
newLight.setColor(new Vector3f(rand.nextFloat(),rand.nextFloat(),rand.nextFloat()).normalize());
rVal.entityPointLightMap.put(EntityCreationUtils.createClientSpatialEntity(),newLight);
}
//
//create direct light ssbo
rVal.dirLightSSBO = new ShaderStorageBuffer(DIRECT_LIGHT_BUFFER_SIZE, BufferUsage.DYNAMIC, BufferAccess.DRAW);
rVal.directionalLight = new DirectionalLight(new Vector3f(0,-1,0));
rVal.directionalLight.setColor(new Vector3f(0.5f));
return rVal;
}
/**
* Computes the light culling clusters based on a camera
* @param renderPipelineState The render pipeline state
* @param openGLState The opengl state
* @param camera The camera
*/
private void computeLightCulling(RenderPipelineState renderPipelineState, OpenGLState openGLState, Entity camera){
openGLState.glViewport(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
//
//Build AABBs
ComputeShader clusterComp = Globals.assetManager.fetchComputeShader(AssetDataStrings.COMPUTE_LIGHT_CLUSTER);
if(clusterComp != null){
openGLState.setActiveShader(renderPipelineState, clusterComp);
clusterComp.setUniform(openGLState, "zNear", CameraEntityUtils.getNearClip(camera));
clusterComp.setUniform(openGLState, "zFar", CameraEntityUtils.getFarClip(camera));
clusterComp.setUniform(openGLState, "inverseProjection", new Matrix4d(Globals.projectionMatrix).invert());
clusterComp.setUniform(openGLState, "gridSize", new Vector3i(LIGHT_CLUSTER_WIDTH_X,LIGHT_CLUSTER_WIDTH_Y,LIGHT_CLUSTER_WIDTH_Z));
clusterComp.setUniform(openGLState, "screenDimensions", openGLState.getViewport());
clusterComp.dispatch(LIGHT_CLUSTER_WIDTH_X,LIGHT_CLUSTER_WIDTH_Y,LIGHT_CLUSTER_WIDTH_Z);
MemoryBarrier.glMemoryBarrier(Barrier.GL_SHADER_STORAGE_BARRIER_BIT);
}
//
//cull lights
ComputeShader lightCull = Globals.assetManager.fetchComputeShader(AssetDataStrings.COMPUTE_LIGHT_CULL);
openGLState.setActiveShader(renderPipelineState, lightCull);
lightCull.setUniform(openGLState, "viewMatrix", Globals.viewMatrix);
int dispatchLocal = (LIGHT_CLUSTER_WIDTH_X * LIGHT_CLUSTER_WIDTH_Y * LIGHT_CLUSTER_WIDTH_Z) / CULL_LOCAL_SIZE;
lightCull.dispatch(dispatchLocal, ComputeShader.DEFAULT_LOCAL_SIZE, ComputeShader.DEFAULT_LOCAL_SIZE);
MemoryBarrier.glMemoryBarrier(Barrier.GL_SHADER_STORAGE_BARRIER_BIT);
}
/**
* Pushes latest data to buffers
*/
private void pushToBuffers(RenderPipelineState renderPipelineState, OpenGLState openGLState, Entity camera){
int i = 0;
//
//push point lights
ByteBuffer pointLightBuffer = pointLightSSBO.getBuffer();
for(PointLight light : this.entityPointLightMap.values()){
if(i >= MAX_POINT_LIGHTS){
LoggerInterface.loggerRenderer.WARNING("CLOSE TO MAXIMUM NUMBER OF POINT LIGHTS!");
break;
}
//
//position
Vector3f modifiedCameraPos = new Vector3f(light.getPosition()).sub(CameraEntityUtils.getCameraCenter(camera));
pointLightBuffer.putFloat(modifiedCameraPos.x);
pointLightBuffer.putFloat(modifiedCameraPos.y);
pointLightBuffer.putFloat(modifiedCameraPos.z);
pointLightBuffer.putFloat(1);
//
//color
pointLightBuffer.putFloat(light.getColor().x);
pointLightBuffer.putFloat(light.getColor().y);
pointLightBuffer.putFloat(light.getColor().z);
pointLightBuffer.putFloat(1);
//
//const
pointLightBuffer.putFloat(light.getConstant());
pointLightBuffer.putFloat(light.getLinear());
pointLightBuffer.putFloat(light.getQuadratic());
pointLightBuffer.putFloat(light.getRadius());
}
pointLightBuffer.flip();
pointLightSSBO.upload(openGLState);
//
//push direct light
ByteBuffer directLightBuffer = dirLightSSBO.getBuffer();
{
//
//direction
directLightBuffer.putFloat(directionalLight.getDirection().x);
directLightBuffer.putFloat(directionalLight.getDirection().y);
directLightBuffer.putFloat(directionalLight.getDirection().z);
//
//color
directLightBuffer.putFloat(directionalLight.getColor().x);
directLightBuffer.putFloat(directionalLight.getColor().y);
directLightBuffer.putFloat(directionalLight.getColor().z);
}
directLightBuffer.flip();
dirLightSSBO.upload(openGLState);
}
/**
* Updates the light manager
* @param renderPipelineState The rendering state
* @param openGLState The opengl state
* @param camera The camera
*/
public void update(RenderPipelineState renderPipelineState, OpenGLState openGLState, Entity camera){
if(camera != null){
this.pushToBuffers(renderPipelineState, openGLState, camera);
this.computeLightCulling(renderPipelineState, openGLState, camera);
}
}
/**
* Gets the cluster grid ssbo
* @return The cluster grid ssbo
*/
public ShaderStorageBuffer getClusterGridSSBO(){
return this.clusterGridSSBO;
}
/**
* Gets the point light ssbo
* @return The point light ssbo
*/
public ShaderStorageBuffer getPointLightSSBO(){
return this.pointLightSSBO;
}
/**
* Gets the direct light ssbo
* @return The direct light ssbo
*/
public ShaderStorageBuffer getDirectLightSSBO(){
return this.dirLightSSBO;
}
/**
* Gets the directional light
* @return The directional light
*/ */
public DirectionalLight getDirectionalLight(){ public DirectionalLight getDirectionalLight(){
return this.directionalLight; return directionalLight;
} }
//
//
// BUFFER MANAGEMENT
//
//
/**
* Call in each mesh / per each shader
* @param shaderIndex
*/
public void bindBuffer(OpenGLState openGLState){
//get position of lights object in shader
int bufferIndex = GL31.glGetUniformBlockIndex(openGLState.getActiveShader().getId(), "Lights");
int glErrorCode = Globals.renderingEngine.getError();
if(glErrorCode != 0){
LoggerInterface.loggerRenderer.DEBUG_LOOP(RenderingEngine.getErrorInEnglish(glErrorCode));
}
if(bufferIndex == ShaderProgram.INVALID_UNIFORM_NAME){
LoggerInterface.loggerRenderer.INFO("Tried to buffer light manager to shader that does not have it active.");
} else {
//bind that position to the slot '2'
GL31.glUniformBlockBinding(openGLState.getActiveShader().getId(), bufferIndex, BIND_POINT);
Globals.renderingEngine.checkError();
//bind our buffer to slot '2' as well
GL31.glBindBufferBase(GL_UNIFORM_BUFFER, BIND_POINT, uboIndex);
Globals.renderingEngine.checkError();
}
//alternatively if want to use range, do glBindBufferRange(GL_UNIFORM_BUFFER, 2, uboExampleBlock, 0, 152);
// Globals.renderingEngine.checkError();
}
/**
* Call once per render loop to set buffer values
*/
public void updateData(){
putDataInBuffer();
bufferData();
}
void bufferData(){
glBindBuffer(GL_UNIFORM_BUFFER, uboIndex);
// int offset = 0;
glBufferData(GL_UNIFORM_BUFFER, dataBuffer, GL_DYNAMIC_DRAW);
// glBufferSubData(GL_UNIFORM_BUFFER, offset, dataBuffer);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
void putDataInBuffer(){
//implicitly flips
dataBuffer.clear();
//direct light
//vec3 dirLightDirection
dataBuffer.putFloat(directionalLight.direction.x);
dataBuffer.putFloat(directionalLight.direction.y);
dataBuffer.putFloat(directionalLight.direction.z);
dataBuffer.putFloat(0);
//vec3 dirLightAmbient
dataBuffer.putFloat(directionalLight.ambient.x);
dataBuffer.putFloat(directionalLight.ambient.y);
dataBuffer.putFloat(directionalLight.ambient.z);
dataBuffer.putFloat(0);
//vec3 dirLightDiffuse
dataBuffer.putFloat(directionalLight.diffuse.x);
dataBuffer.putFloat(directionalLight.diffuse.y);
dataBuffer.putFloat(directionalLight.diffuse.z);
dataBuffer.putFloat(0);
//vec3 dirLightSpecular
dataBuffer.putFloat(directionalLight.specular.x);
dataBuffer.putFloat(directionalLight.specular.y);
dataBuffer.putFloat(directionalLight.specular.z);
dataBuffer.putFloat(0);
//point light
//vec3 position[10]
//dont sub cam
// for(int i = 0; i < POINT_LIGHT_COUNT; i++){
// PointLight light = pointLights[i];
// dataBuffer.putFloat(light.position.x);
// dataBuffer.putFloat(light.position.y);
// dataBuffer.putFloat(light.position.z);
// dataBuffer.putFloat(0);
// }
//do sub cam
if(Globals.playerCamera != null){
Vector3f cameraPos = CameraEntityUtils.getCameraCenter(Globals.playerCamera);
for(int i = 0; i < POINT_LIGHT_COUNT; i++){
PointLight light = pointLights[i];
dataBuffer.putFloat(light.position.x - cameraPos.x);
dataBuffer.putFloat(light.position.y - cameraPos.y);
dataBuffer.putFloat(light.position.z - cameraPos.z);
dataBuffer.putFloat(0);
}
}
//float constant[10]
for(int i = 0; i < POINT_LIGHT_COUNT; i++){
PointLight light = pointLights[i];
dataBuffer.putFloat(light.constant);
dataBuffer.putFloat(0);
dataBuffer.putFloat(0);
dataBuffer.putFloat(0);
}
//float linear[10]
for(int i = 0; i < POINT_LIGHT_COUNT; i++){
PointLight light = pointLights[i];
dataBuffer.putFloat(light.linear);
dataBuffer.putFloat(0);
dataBuffer.putFloat(0);
dataBuffer.putFloat(0);
}
//float quadratic[10]
for(int i = 0; i < POINT_LIGHT_COUNT; i++){
PointLight light = pointLights[i];
dataBuffer.putFloat(light.quadratic);
dataBuffer.putFloat(0);
dataBuffer.putFloat(0);
dataBuffer.putFloat(0);
}
//vec3 ambient[10]
for(int i = 0; i < POINT_LIGHT_COUNT; i++){
PointLight light = pointLights[i];
dataBuffer.putFloat(light.ambient.x);
dataBuffer.putFloat(light.ambient.y);
dataBuffer.putFloat(light.ambient.z);
dataBuffer.putFloat(0);
}
//vec3 diffuse[10]
for(int i = 0; i < POINT_LIGHT_COUNT; i++){
PointLight light = pointLights[i];
dataBuffer.putFloat(light.diffuse.x);
dataBuffer.putFloat(light.diffuse.y);
dataBuffer.putFloat(light.diffuse.z);
dataBuffer.putFloat(0);
}
//vec3 specular[10]
for(int i = 0; i < POINT_LIGHT_COUNT; i++){
PointLight light = pointLights[i];
dataBuffer.putFloat(light.specular.x);
dataBuffer.putFloat(light.specular.y);
dataBuffer.putFloat(light.specular.z);
dataBuffer.putFloat(0);
}
if(dataBuffer.position() > 0){
dataBuffer.flip();
}
// dataBuffer.position(0);
}
} }

View File

@ -10,9 +10,8 @@ public class PointLight {
float constant; float constant;
float linear; float linear;
float quadratic; float quadratic;
Vector3f ambient; float radius;
Vector3f diffuse; Vector3f color;
Vector3f specular;
public void setPosition(Vector3f position) { public void setPosition(Vector3f position) {
this.position = position; this.position = position;
@ -30,16 +29,12 @@ public class PointLight {
this.quadratic = quadratic; this.quadratic = quadratic;
} }
public void setAmbient(Vector3f ambient) { public void setRadius(float radius){
this.ambient = ambient; this.radius = radius;
} }
public void setDiffuse(Vector3f diffuse) { public void setColor(Vector3f color){
this.diffuse = diffuse; this.color = color;
}
public void setSpecular(Vector3f specular) {
this.specular = specular;
} }
public Vector3f getPosition() { public Vector3f getPosition() {
@ -58,43 +53,29 @@ public class PointLight {
return quadratic; return quadratic;
} }
public Vector3f getAmbient() { public Vector3f getColor(){
return ambient; return color;
} }
public Vector3f getDiffuse() { public float getRadius(){
return diffuse; return radius;
}
public Vector3f getSpecular() {
return specular;
} }
public PointLight(Vector3f position){ public PointLight(Vector3f position){
this.position = position; this.position = position;
radius = 1;
constant = 1.0f; constant = 1.0f;
linear = 0.01f; linear = 0.7f;
quadratic = 0.01f; quadratic = 1.8f;
ambient = new Vector3f(0.05f, 0.05f, 0.05f); color = new Vector3f(1.0f);
diffuse = new Vector3f(0.8f, 0.8f, 0.8f);
specular = new Vector3f(1.0f, 1.0f, 1.0f);
this.position.normalize();
ambient.normalize();
diffuse.normalize();
specular.normalize();
} }
public PointLight(Vector3f position, Vector3f color){ public PointLight(Vector3f position, Vector3f color){
this.position = position; this.position = position;
radius = 1;
constant = 1.0f; constant = 1.0f;
linear = 0.01f; linear = 0.7f;
quadratic = 0.01f; quadratic = 1.8f;
ambient = new Vector3f(color.x * 0.05f, color.y * 0.05f, color.z * 0.05f); this.color = color;
diffuse = new Vector3f(color.x * 0.8f, color.y * 0.8f, color.z * 0.8f);
specular = new Vector3f(color.x, color.y, color.z);
this.position.normalize();
ambient.normalize();
diffuse.normalize();
specular.normalize();
} }
} }

View File

@ -21,6 +21,7 @@ import org.joml.Matrix4d;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Sphered; import org.joml.Sphered;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector3i;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL15;
@ -354,7 +355,16 @@ public class Mesh {
//don't buffer as the light manager hasn't initialized //don't buffer as the light manager hasn't initialized
} else { } else {
LightManager lightManager = Globals.renderingEngine.getLightManager(); LightManager lightManager = Globals.renderingEngine.getLightManager();
lightManager.bindBuffer(openGLState); openGLState.glBindBufferBase(LightManager.CLUSTER_SSBO_BIND_POINT, lightManager.getClusterGridSSBO());
openGLState.glBindBufferBase(LightManager.POINT_LIGHT_SSBO_BIND_POINT, lightManager.getPointLightSSBO());
openGLState.glBindBufferBase(LightManager.DIRECT_LIGHT_SSBO_BIND_POINT, lightManager.getDirectLightSSBO());
//set uniforms required
openGLState.getActiveShader().setUniform(openGLState, "zNear", CameraEntityUtils.getNearClip(Globals.playerCamera));
openGLState.getActiveShader().setUniform(openGLState, "zFar", CameraEntityUtils.getFarClip(Globals.playerCamera));
openGLState.getActiveShader().setUniform(openGLState, "gridSize", new Vector3i(LightManager.LIGHT_CLUSTER_WIDTH_X,LightManager.LIGHT_CLUSTER_WIDTH_Y,LightManager.LIGHT_CLUSTER_WIDTH_Z));
openGLState.getActiveShader().setUniform(openGLState, "screenDimensions", openGLState.getViewport());
} }
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
} }

View File

@ -5,7 +5,11 @@ import java.util.Map;
import org.joml.Matrix4d; import org.joml.Matrix4d;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Vector2d;
import org.joml.Vector2i;
import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector3i;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL40; import org.lwjgl.opengl.GL40;
import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45;
@ -21,6 +25,11 @@ import electrosphere.renderer.RenderingEngine;
*/ */
public class ComputeShader implements Shader { public class ComputeShader implements Shader {
/**
* The default local size
*/
public static final int DEFAULT_LOCAL_SIZE = 1;
/** /**
* The id for the shader * The id for the shader
*/ */
@ -86,14 +95,7 @@ public class ComputeShader implements Shader {
*/ */
public void dispatch(int x, int y, int z){ public void dispatch(int x, int y, int z){
GL45.glDispatchCompute(x, y, z); GL45.glDispatchCompute(x, y, z);
} Globals.renderingEngine.checkError();
/**
* Sets the memory barrier value
* @param value The value
*/
public void memoryBarier(int value){
GL45.glMemoryBarrier(value);
} }
/** /**
@ -164,7 +166,39 @@ public class ComputeShader implements Shader {
Vector3f currentUniform = (Vector3f)value; Vector3f currentUniform = (Vector3f)value;
GL40.glUniform3fv(uniformLocation, currentUniform.get(BufferUtils.createFloatBuffer(3))); GL40.glUniform3fv(uniformLocation, currentUniform.get(BufferUtils.createFloatBuffer(3)));
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
uniformMap.put(uniformLocation,new Vector3f(currentUniform)); //create new matrix4f to break pointer-matching with equals on cache check uniformMap.put(uniformLocation,new Vector3f(currentUniform)); //create new vector3f to break pointer-matching with equals on cache check
//
//vector3d
} else if(value instanceof Vector3d){
Vector3d currentUniform = (Vector3d)value;
GL40.glUniform3dv(uniformLocation, currentUniform.get(BufferUtils.createDoubleBuffer(3)));
Globals.renderingEngine.checkError();
uniformMap.put(uniformLocation,new Vector3d(currentUniform)); //create new vector3d to break pointer-matching with equals on cache check
//
//vector2d
} else if(value instanceof Vector2d){
Vector2d currentUniform = (Vector2d)value;
GL40.glUniform2dv(uniformLocation, currentUniform.get(BufferUtils.createDoubleBuffer(2)));
Globals.renderingEngine.checkError();
uniformMap.put(uniformLocation,new Vector2d(currentUniform)); //create new vector2d to break pointer-matching with equals on cache check
//
//Vector3i
} else if(value instanceof Vector3i){
Vector3i currentUniform = (Vector3i)value;
GL40.glUniform3uiv(uniformLocation, currentUniform.get(BufferUtils.createIntBuffer(3)));
Globals.renderingEngine.checkError();
uniformMap.put(uniformLocation,new Vector3i(currentUniform)); //create new vector2d to break pointer-matching with equals on cache check
//
//Vector2i
} else if(value instanceof Vector2i){
Vector2i currentUniform = (Vector2i)value;
GL40.glUniform2uiv(uniformLocation, currentUniform.get(BufferUtils.createIntBuffer(2)));
Globals.renderingEngine.checkError();
uniformMap.put(uniformLocation,new Vector2i(currentUniform)); //create new vector2d to break pointer-matching with equals on cache check
// //
//integer //integer

View File

@ -2,6 +2,8 @@ package electrosphere.renderer.shader;
import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45;
import electrosphere.engine.Globals;
/** /**
* Memory barrier operations * Memory barrier operations
*/ */
@ -152,7 +154,9 @@ public class MemoryBarrier {
} }
/** /**
* Sets the memory barrier * Sets the memory barrier.
* Essentially halts CPU execution until the given barrier is cleared.
* IE, if GL_SHADER_STORAGE_BARRIER_BIT is passed, the CPU will wait until the SSBO values are fully set before continuing execution.
* @param barrier The barrier to set * @param barrier The barrier to set
*/ */
public static void glMemoryBarrier(Barrier barrier){ public static void glMemoryBarrier(Barrier barrier){
@ -205,6 +209,7 @@ public class MemoryBarrier {
} break; } break;
} }
GL45.glMemoryBarrier(barrierVal); GL45.glMemoryBarrier(barrierVal);
Globals.renderingEngine.checkError();
} }
} }

View File

@ -29,7 +29,11 @@ import javax.management.RuntimeErrorException;
import org.joml.Matrix4d; import org.joml.Matrix4d;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Vector2d;
import org.joml.Vector2i;
import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector3i;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL40; import org.lwjgl.opengl.GL40;
@ -704,6 +708,38 @@ public class ShaderProgram implements Shader {
Globals.renderingEngine.checkError(); Globals.renderingEngine.checkError();
uniformMap.put(uniformLocation,new Vector3f(currentUniform)); //create new matrix4f to break pointer-matching with equals on cache check uniformMap.put(uniformLocation,new Vector3f(currentUniform)); //create new matrix4f to break pointer-matching with equals on cache check
//
//vector3d
} else if(value instanceof Vector3d){
Vector3d currentUniform = (Vector3d)value;
GL40.glUniform3dv(uniformLocation, currentUniform.get(BufferUtils.createDoubleBuffer(3)));
Globals.renderingEngine.checkError();
uniformMap.put(uniformLocation,new Vector3d(currentUniform)); //create new vector3d to break pointer-matching with equals on cache check
//
//vector2d
} else if(value instanceof Vector2d){
Vector2d currentUniform = (Vector2d)value;
GL40.glUniform2dv(uniformLocation, currentUniform.get(BufferUtils.createDoubleBuffer(2)));
Globals.renderingEngine.checkError();
uniformMap.put(uniformLocation,new Vector2d(currentUniform)); //create new vector2d to break pointer-matching with equals on cache check
//
//Vector3i
} else if(value instanceof Vector3i){
Vector3i currentUniform = (Vector3i)value;
GL40.glUniform3uiv(uniformLocation, currentUniform.get(BufferUtils.createIntBuffer(3)));
Globals.renderingEngine.checkError();
uniformMap.put(uniformLocation,new Vector3i(currentUniform)); //create new vector2d to break pointer-matching with equals on cache check
//
//Vector2i
} else if(value instanceof Vector2i){
Vector2i currentUniform = (Vector2i)value;
GL40.glUniform2uiv(uniformLocation, currentUniform.get(BufferUtils.createIntBuffer(2)));
Globals.renderingEngine.checkError();
uniformMap.put(uniformLocation,new Vector2i(currentUniform)); //create new vector2d to break pointer-matching with equals on cache check
// //
//integer //integer
} else if(value instanceof Integer){ } else if(value instanceof Integer){

View File

@ -48,7 +48,7 @@ public class ShaderStorageBufferTests extends RenderingTestTemplate {
public void test_upload_NoThrow(){ public void test_upload_NoThrow(){
assertDoesNotThrow(() -> { assertDoesNotThrow(() -> {
ShaderStorageBuffer buffer = new ShaderStorageBuffer(10, BufferUsage.STATIC, BufferAccess.READ); ShaderStorageBuffer buffer = new ShaderStorageBuffer(10, BufferUsage.STATIC, BufferAccess.READ);
buffer.upload(); buffer.upload(Globals.renderingEngine.getOpenGLState());
}); });
} }