clustered lighting implementation
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
5eeb281e0b
commit
dc52e375e3
@ -1,37 +1,66 @@
|
||||
#version 330 core
|
||||
#version 450 core
|
||||
|
||||
//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;
|
||||
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
layout (std140) uniform Lights {
|
||||
// this is how many because we have to align
|
||||
// bytes it SHOULD in multiples of 16, this
|
||||
// take it where it ACTUALLY is
|
||||
//
|
||||
//refer: https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL
|
||||
//
|
||||
// base alignment aligned offset
|
||||
//direct light
|
||||
vec3 dLDirection; // 16 0
|
||||
vec3 dLAmbient; // 16 16
|
||||
vec3 dLDiffuse; // 16 32
|
||||
vec3 dLSpecular; // 16 48
|
||||
|
||||
//point light
|
||||
vec3 pLposition[NR_POINT_LIGHTS]; // 16*10 64
|
||||
float pLconstant[NR_POINT_LIGHTS]; // 16*10 224
|
||||
float pLlinear[NR_POINT_LIGHTS]; // 16*10 384
|
||||
float pLquadratic[NR_POINT_LIGHTS]; // 16*10 544
|
||||
vec3 pLambient[NR_POINT_LIGHTS]; // 16*10 704
|
||||
vec3 pLdiffuse[NR_POINT_LIGHTS]; // 16*10 864
|
||||
vec3 pLspecular[NR_POINT_LIGHTS]; // 16*10 1024
|
||||
|
||||
//for a total size of 1184
|
||||
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
@ -41,6 +70,7 @@ struct Material {
|
||||
};
|
||||
|
||||
in vec3 FragPos;
|
||||
in vec3 ViewFragPos;
|
||||
in vec3 Normal;
|
||||
in vec2 TexCoord;
|
||||
in vec4 FragPosLightSpace;
|
||||
@ -60,11 +90,18 @@ uniform int hasTransparency;
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
|
||||
|
||||
// function prototypes
|
||||
// vec3 CalcDirLight(vec3 normal, vec3 viewDir);
|
||||
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
// vec3 CalcSpotLight(vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
|
||||
@ -76,54 +113,47 @@ void main(){
|
||||
vec3 viewDir = normalize(viewPos - FragPos);
|
||||
|
||||
//grab light intensity
|
||||
float lightIntensity = calcLightIntensityTotal(norm);
|
||||
vec3 lightIntensity = vec3(calcLightIntensityTotal(norm));
|
||||
|
||||
//get color of base texture
|
||||
vec3 textureColor = texture(material.diffuse, TexCoord).rgb;
|
||||
|
||||
//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
|
||||
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
|
||||
FragColor = vec4(finalColor, texture(material.diffuse, TexCoord).a);//texture(ourTexture, TexCoord);//vec4(result, 1.0);
|
||||
}
|
||||
|
||||
// calculates the color when using a directional light.
|
||||
// vec3 CalcDirLight(vec3 normal, vec3 viewDir){
|
||||
// vec3 lightDir = normalize(-dLDirection);
|
||||
// // diffuse shading
|
||||
// float diff = max(dot(normal, lightDir), 0.0);
|
||||
// // specular shading
|
||||
// // vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// // combine results
|
||||
// vec3 texColor = texture(material.diffuse, TexCoord).rgb;
|
||||
// vec3 diffuse = dLDiffuse * diff;
|
||||
// //vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord).rgb);
|
||||
|
||||
|
||||
// float shadow = ShadowCalculation(FragPosLightSpace, lightDir, normal);
|
||||
|
||||
// return ( dLAmbient + (1.0-shadow) * diffuse ) * texColor;// + specular);
|
||||
// }
|
||||
|
||||
//
|
||||
float calcLightIntensityAmbient(){
|
||||
//calculate average of ambient light
|
||||
float avg = (dLAmbient.x + dLAmbient.y + dLAmbient.z)/3.0;
|
||||
float avg = (directLight.color.x + directLight.color.y + directLight.color.z)/3.0;
|
||||
return avg;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-dLDirection);
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
@ -146,63 +176,53 @@ float calcLightIntensityTotal(vec3 normal){
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal);
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pLposition[i] - fragPos);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pLposition[i] - fragPos);
|
||||
float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance));
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient *= attenuation;
|
||||
diffuse *= attenuation;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = 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));
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
// // calculates the color when using a point light.
|
||||
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
// vec3 lightDir = normalize(pLposition[i] - fragPos);
|
||||
// // diffuse shading
|
||||
// float diff = max(dot(normal, lightDir), 0.0);
|
||||
// // specular shading
|
||||
// // vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// // attenuation
|
||||
// float distance = length(pLposition[i] - fragPos);
|
||||
// float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance));
|
||||
// // combine results
|
||||
// vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// // vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
// ambient *= attenuation;
|
||||
// diffuse *= attenuation;
|
||||
// // specular *= attenuation;
|
||||
// vec3 specular = vec3(0,0,0);
|
||||
|
||||
// vec3 finalValue = (ambient + diffuse + specular);
|
||||
// finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
|
||||
// return finalValue;
|
||||
// }
|
||||
/**
|
||||
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){
|
||||
|
||||
@ -30,6 +30,7 @@ uniform int numBones;
|
||||
//output buffers
|
||||
out vec3 Normal;
|
||||
out vec3 FragPos;
|
||||
out vec3 ViewFragPos;
|
||||
out vec2 TexCoord;
|
||||
out vec4 FragPosLightSpace;
|
||||
|
||||
@ -59,6 +60,7 @@ void main() {
|
||||
|
||||
//push frag, normal, and texture positions to fragment shader
|
||||
FragPos = vec3(model * FinalVertex);
|
||||
ViewFragPos = vec3(view * model * FinalVertex);
|
||||
Normal = mat3(transpose(inverse(model))) * FinalNormal.xyz;
|
||||
TexCoord = aTex;
|
||||
|
||||
|
||||
97
assets/Shaders/core/light/cluster.comp
Normal file
97
assets/Shaders/core/light/cluster.comp
Normal 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;
|
||||
}
|
||||
87
assets/Shaders/core/light/cull.comp
Normal file
87
assets/Shaders/core/light/cull.comp
Normal 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);
|
||||
}
|
||||
@ -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 = 1) out float reveal;
|
||||
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
layout (std140) uniform Lights {
|
||||
// this is how many because we have to align
|
||||
// bytes it SHOULD in multiples of 16, this
|
||||
// take it where it ACTUALLY is
|
||||
//
|
||||
//refer: https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL
|
||||
//
|
||||
// base alignment aligned offset
|
||||
//direct light
|
||||
vec3 dLDirection; // 16 0
|
||||
vec3 dLAmbient; // 16 16
|
||||
vec3 dLDiffuse; // 16 32
|
||||
vec3 dLSpecular; // 16 48
|
||||
|
||||
//point light
|
||||
vec3 pLposition[NR_POINT_LIGHTS]; // 16*10 64
|
||||
float pLconstant[NR_POINT_LIGHTS]; // 16*10 224
|
||||
float pLlinear[NR_POINT_LIGHTS]; // 16*10 384
|
||||
float pLquadratic[NR_POINT_LIGHTS]; // 16*10 544
|
||||
vec3 pLambient[NR_POINT_LIGHTS]; // 16*10 704
|
||||
vec3 pLdiffuse[NR_POINT_LIGHTS]; // 16*10 864
|
||||
vec3 pLspecular[NR_POINT_LIGHTS]; // 16*10 1024
|
||||
|
||||
//for a total size of 1184
|
||||
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
@ -42,6 +73,7 @@ struct Material {
|
||||
|
||||
//inputs
|
||||
in vec3 FragPos;
|
||||
in vec3 ViewFragPos;
|
||||
in vec3 Normal;
|
||||
in vec2 TexCoord;
|
||||
in vec4 FragPosLightSpace;
|
||||
@ -58,9 +90,20 @@ uniform Material material;
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
uniform mat4 view;
|
||||
|
||||
|
||||
//function prototypes
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
uint findCluster(vec3 FragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
float linearizeDepth(float d,float zNear,float zFar);
|
||||
float weightCalcOrigin(float finalAlpha, float zLoc, float linearizedLoc);
|
||||
@ -74,17 +117,33 @@ void main(){
|
||||
vec3 viewDir = normalize(viewPos - FragPos);
|
||||
|
||||
//grab light intensity
|
||||
float lightIntensity = calcLightIntensityTotal(norm);
|
||||
vec3 lightIntensity = vec3(calcLightIntensityTotal(norm));
|
||||
|
||||
//get color of base texture
|
||||
vec4 textureColor = texture(material.diffuse, TexCoord);
|
||||
vec3 textureRGB = textureColor.rgb;
|
||||
|
||||
//shadow
|
||||
float shadow = ShadowCalculation(FragPosLightSpace, normalize(-dLDirection), norm);
|
||||
vec3 shadowModifiedColor = textureRGB * lightIntensity * max(shadow, 0.4);
|
||||
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){
|
||||
accum = vec4(1.0f,0.0f,0.0f,1);
|
||||
reveal = textureColor.a;
|
||||
return;
|
||||
}
|
||||
|
||||
//calculate final color
|
||||
vec3 shadowModifiedColor = textureRGB * lightIntensity * max(shadow, 0.4);
|
||||
vec4 finalColor = vec4(shadowModifiedColor,textureColor.a);
|
||||
|
||||
//calculate weight function
|
||||
@ -127,13 +186,13 @@ float linearizeDepth(float d,float zNear,float zFar){
|
||||
|
||||
float calcLightIntensityAmbient(){
|
||||
//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;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-dLDirection);
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
@ -156,38 +215,55 @@ float calcLightIntensityTotal(vec3 normal){
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal);
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pLposition[i] - fragPos);
|
||||
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pLposition[i] - fragPos);
|
||||
float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance));
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient *= attenuation;
|
||||
diffuse *= attenuation;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = 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));
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the light cluster this fragment belongs to
|
||||
*/
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
|
||||
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
|
||||
vec2 tileSize = screenDimensions / gridSize.xy;
|
||||
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
|
||||
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@ uniform int numBones;
|
||||
//output buffers
|
||||
out vec3 Normal;
|
||||
out vec3 FragPos;
|
||||
out vec3 ViewFragPos;
|
||||
out vec2 TexCoord;
|
||||
out vec4 FragPosLightSpace;
|
||||
|
||||
@ -59,6 +60,7 @@ void main() {
|
||||
|
||||
//push frag, normal, and texture positions to fragment shader
|
||||
FragPos = vec3(model * FinalVertex);
|
||||
ViewFragPos = vec3(view * model * FinalVertex);
|
||||
Normal = mat3(transpose(inverse(model))) * FinalNormal.xyz;
|
||||
TexCoord = aTex;
|
||||
|
||||
|
||||
@ -1,37 +1,68 @@
|
||||
#version 330 core
|
||||
#version 450 core
|
||||
|
||||
//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;
|
||||
|
||||
|
||||
layout (std140) uniform Lights {
|
||||
// this is how many because we have to align
|
||||
// bytes it SHOULD in multiples of 16, this
|
||||
// take it where it ACTUALLY is
|
||||
//
|
||||
//refer: https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL
|
||||
//
|
||||
// base alignment aligned offset
|
||||
//direct light
|
||||
vec3 dLDirection; // 16 0
|
||||
vec3 dLAmbient; // 16 16
|
||||
vec3 dLDiffuse; // 16 32
|
||||
vec3 dLSpecular; // 16 48
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
//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 = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
@ -41,6 +72,7 @@ struct Material {
|
||||
};
|
||||
|
||||
in vec3 FragPos;
|
||||
in vec3 ViewFragPos;
|
||||
in vec3 Normal;
|
||||
in vec2 TexCoord;
|
||||
in vec4 FragPosLightSpace;
|
||||
@ -62,11 +94,19 @@ uniform int hasTransparency;
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
uniform mat4 view;
|
||||
|
||||
|
||||
// function prototypes
|
||||
// vec3 CalcDirLight(vec3 normal, vec3 viewDir);
|
||||
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
// vec3 CalcSpotLight(vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
uint findCluster(vec3 FragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
float easeIn(float interpolator);
|
||||
@ -90,7 +130,7 @@ void main(){
|
||||
vec3 viewDir = normalize(viewPos - FragPos);
|
||||
|
||||
//grab light intensity
|
||||
float lightIntensity = calcLightIntensityTotal(norm);
|
||||
vec3 lightIntensity = vec3(calcLightIntensityTotal(norm));
|
||||
|
||||
//get color of base texture
|
||||
// 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;
|
||||
|
||||
//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
|
||||
vec3 finalColor = textureColor * lightIntensity;// * max(shadow,0.4);
|
||||
@ -133,13 +188,13 @@ void main(){
|
||||
//
|
||||
float calcLightIntensityAmbient(){
|
||||
//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;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-dLDirection);
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
@ -162,64 +217,53 @@ float calcLightIntensityTotal(vec3 normal){
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal);
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pLposition[i] - fragPos);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pLposition[i] - fragPos);
|
||||
float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance));
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient *= attenuation;
|
||||
diffuse *= attenuation;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = 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));
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
// // calculates the color when using a point light.
|
||||
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
// vec3 lightDir = normalize(pLposition[i] - fragPos);
|
||||
// // diffuse shading
|
||||
// float diff = max(dot(normal, lightDir), 0.0);
|
||||
// // specular shading
|
||||
// // vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// // float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// // attenuation
|
||||
// float distance = length(pLposition[i] - fragPos);
|
||||
// float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance));
|
||||
// // combine results
|
||||
// vec3 ambient = pLambient[i];// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 diffuse = pLdiffuse[i] * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// // vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
// ambient *= attenuation;
|
||||
// diffuse *= attenuation;
|
||||
// // specular *= attenuation;
|
||||
// vec3 specular = vec3(0,0,0);
|
||||
|
||||
// vec3 finalValue = (ambient + diffuse + specular);
|
||||
// finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
|
||||
// return finalValue;
|
||||
// }
|
||||
|
||||
/**
|
||||
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){
|
||||
|
||||
|
||||
@ -40,6 +40,7 @@ uniform float time;
|
||||
//output buffers
|
||||
out vec3 Normal;
|
||||
out vec3 FragPos;
|
||||
out vec3 ViewFragPos;
|
||||
out vec2 TexCoord;
|
||||
out vec4 FragPosLightSpace;
|
||||
out vec3 normalRot1;
|
||||
@ -156,6 +157,7 @@ void main() {
|
||||
//push frag, normal, and texture positions to fragment shader
|
||||
//
|
||||
FragPos = vec3(FinalVertex);
|
||||
ViewFragPos = vec3(view * model * FinalVertex);
|
||||
Normal = vec3(FinalNormal);
|
||||
TexCoord = aTex;
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#version 330 core
|
||||
#version 450 core
|
||||
|
||||
//texture defines
|
||||
#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 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;
|
||||
|
||||
layout(std430, binding = CLUSTER_SSBO_BIND_POINT) restrict buffer clusterGridSSBO {
|
||||
Cluster clusters[];
|
||||
};
|
||||
|
||||
layout (std140) uniform Lights {
|
||||
// this is how many because we have to align
|
||||
// bytes it SHOULD in multiples of 16, this
|
||||
// take it where it ACTUALLY is
|
||||
//
|
||||
//refer: https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL
|
||||
//
|
||||
// base alignment aligned offset
|
||||
//direct light
|
||||
vec3 dLDirection; // 16 0
|
||||
vec3 dLAmbient; // 16 16
|
||||
vec3 dLDiffuse; // 16 32
|
||||
vec3 dLSpecular; // 16 48
|
||||
|
||||
//point light
|
||||
vec3 pLposition[NR_POINT_LIGHTS]; // 16*10 64
|
||||
float pLconstant[NR_POINT_LIGHTS]; // 16*10 224
|
||||
float pLlinear[NR_POINT_LIGHTS]; // 16*10 384
|
||||
float pLquadratic[NR_POINT_LIGHTS]; // 16*10 544
|
||||
vec3 pLambient[NR_POINT_LIGHTS]; // 16*10 704
|
||||
vec3 pLdiffuse[NR_POINT_LIGHTS]; // 16*10 864
|
||||
vec3 pLspecular[NR_POINT_LIGHTS]; // 16*10 1024
|
||||
|
||||
//for a total size of 1184
|
||||
layout(std430, binding = POINT_LIGHT_SSBO_BIND_POINT) restrict buffer pointLightSSBO {
|
||||
PointLight pointLight[];
|
||||
};
|
||||
|
||||
layout(std430, binding = DIRECT_LIGHT_SSBO_BIND_POINT) restrict buffer dirLightSSBO {
|
||||
DirectLight directLight;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
@ -48,6 +78,7 @@ struct Material {
|
||||
};
|
||||
|
||||
in vec3 FragPos;
|
||||
in vec3 ViewFragPos;
|
||||
in vec3 Normal;
|
||||
in vec2 texPlane1;
|
||||
in vec2 texPlane2;
|
||||
@ -71,11 +102,19 @@ uniform int hasTransparency;
|
||||
//light depth map
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
/**
|
||||
Used for light cluster calculation
|
||||
*/
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
uniform uvec3 gridSize;
|
||||
uniform uvec2 screenDimensions;
|
||||
uniform mat4 view;
|
||||
|
||||
|
||||
// function prototypes
|
||||
// vec3 CalcDirLight(vec3 normal, vec3 viewDir);
|
||||
// vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
// vec3 CalcSpotLight(vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
uint findCluster(vec3 FragPos, float zNear, float zFar);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
float calcLightIntensityTotal(vec3 normal);
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal);
|
||||
vec3 getColor(vec2 texPlane1, vec2 texPlane2, vec2 texPlane3, vec3 normal, vec3 samplerIndexVec, vec3 samplerRatioVec, Material material);
|
||||
@ -85,20 +124,31 @@ void main(){
|
||||
vec3 viewDir = normalize(viewPos - FragPos);
|
||||
|
||||
//grab light intensity
|
||||
float lightIntensity = calcLightIntensityTotal(norm);
|
||||
vec3 lightIntensity = vec3(calcLightIntensityTotal(norm));
|
||||
|
||||
//get color of base texture
|
||||
vec3 textureColor = getColor(texPlane1, texPlane2, texPlane3, norm, samplerIndexVec, samplerRatioVec, material);
|
||||
|
||||
//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
|
||||
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
|
||||
FragColor = vec4(finalColor, 1);
|
||||
@ -188,13 +238,13 @@ vec3 getColor(vec2 texPlane1, vec2 texPlane2, vec2 texPlane3, vec3 normal, vec3
|
||||
//
|
||||
float calcLightIntensityAmbient(){
|
||||
//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;
|
||||
}
|
||||
|
||||
//
|
||||
float calcLightIntensityDir(vec3 normal){
|
||||
vec3 lightDir = normalize(-dLDirection);
|
||||
vec3 lightDir = normalize(-directLight.direction);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
@ -217,37 +267,54 @@ float calcLightIntensityTotal(vec3 normal){
|
||||
//
|
||||
vec3 getTotalLightColor(vec3 normal){
|
||||
//get the direct light color adjusted for intensity
|
||||
vec3 diffuseLightColor = dLDiffuse * calcLightIntensityDir(normal);
|
||||
vec3 diffuseLightColor = directLight.color * calcLightIntensityDir(normal);
|
||||
|
||||
//sum light colors
|
||||
vec3 totalLightColor = diffuseLightColor;
|
||||
return totalLightColor;
|
||||
}
|
||||
|
||||
vec3 CalcPointLight(int i, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pLposition[i] - fragPos);
|
||||
vec3 CalcPointLight(PointLight pointLight, vec3 normal, vec3 fragPos, vec3 viewDir){
|
||||
vec3 lightDir = normalize(pointLight.position.xyz - fragPos);
|
||||
// diffuse shading
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
// specular shading
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
// attenuation
|
||||
float distance = length(pLposition[i] - fragPos);
|
||||
float attenuation = 1.0 / (pLconstant[i] + pLlinear[i] * distance + pLquadratic[i] * (distance * distance));
|
||||
float distance = length(pointLight.position.xyz - fragPos);
|
||||
float attenuation = 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
|
||||
if(distance > pointLight.radius){
|
||||
attenuation = 0;
|
||||
}
|
||||
// combine results
|
||||
vec3 ambient = pLambient[i];
|
||||
vec3 diffuse = pLdiffuse[i] * diff;
|
||||
ambient *= attenuation;
|
||||
diffuse *= attenuation;
|
||||
vec3 ambient = pointLight.color.xyz;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
vec3 diffuse = pointLight.color.xyz * diff;// * vec4(texture(material.diffuse, TexCoord)).xyz;
|
||||
// vec3 specular = pLspecular[i] * spec;// * vec4(texture(material.specular, TexCoord)).xyz;
|
||||
ambient = ambient * attenuation;
|
||||
diffuse = diffuse * attenuation;
|
||||
// specular *= attenuation;
|
||||
vec3 specular = vec3(0,0,0);
|
||||
|
||||
vec3 finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
vec3 finalValue = vec3(0);
|
||||
if(distance < pointLight.radius){
|
||||
finalValue = (ambient + diffuse + specular);
|
||||
finalValue = vec3(max(finalValue.x,0),max(finalValue.y,0),max(finalValue.z,0));
|
||||
}
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the light cluster this fragment belongs to
|
||||
*/
|
||||
uint findCluster(vec3 viewspaceFragPos, float zNear, float zFar){
|
||||
uint zTile = uint((log(abs(viewspaceFragPos.z) / zNear) * gridSize.z) / log(zFar / zNear));
|
||||
vec2 tileSize = screenDimensions / gridSize.xy;
|
||||
uvec3 tile = uvec3(gl_FragCoord.xy / tileSize, zTile);
|
||||
return tile.x + (tile.y * gridSize.x) + (tile.z * gridSize.x * gridSize.y);
|
||||
}
|
||||
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightDir, vec3 normal){
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@ uniform mat4 lightSpaceMatrix;
|
||||
//output buffers
|
||||
out vec3 Normal;
|
||||
out vec3 FragPos;
|
||||
out vec3 ViewFragPos;
|
||||
out vec2 texPlane1;
|
||||
out vec2 texPlane2;
|
||||
out vec2 texPlane3;
|
||||
@ -44,6 +45,7 @@ void main() {
|
||||
|
||||
//push frag, normal, and texture positions to fragment shader
|
||||
FragPos = vec3(model * FinalVertex);
|
||||
ViewFragPos = vec3(view * model * FinalVertex);
|
||||
Normal = mat3(transpose(inverse(model))) * aNormal;
|
||||
|
||||
//reference https://catlikecoding.com/unity/tutorials/advanced-rendering/triplanar-mapping/
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
#maven.buildNumber.plugin properties file
|
||||
#Mon Sep 16 19:58:57 EDT 2024
|
||||
buildNumber=333
|
||||
#Wed Sep 18 20:37:06 EDT 2024
|
||||
buildNumber=338
|
||||
|
||||
@ -5,13 +5,21 @@ Design notes for the chemistry system
|
||||
|
||||
Ideas for the chemistry system:
|
||||
- fire
|
||||
- Torch
|
||||
- Fire Arrow
|
||||
- water
|
||||
- bucket
|
||||
- electricity
|
||||
- lightning arrow
|
||||
- ice
|
||||
- ice chunk/block
|
||||
- light
|
||||
- Glittering chunk
|
||||
- Wind/fans
|
||||
- Placeable fan
|
||||
- gravity
|
||||
- stabilization
|
||||
- metal parts / conductivity
|
||||
- light
|
||||
- mirrors
|
||||
- plants burning
|
||||
- plants growing really fast
|
||||
@ -20,6 +28,5 @@ Ideas for the chemistry system:
|
||||
- spinning mechanisms and gears
|
||||
- weighing things down and measuring scales w/ weight
|
||||
- trampolines
|
||||
- Wind/fans
|
||||
- Weight
|
||||
- Music
|
||||
@ -37,6 +37,8 @@
|
||||
- Spawn player in a town with a quest to complete a nearby dungeon
|
||||
|
||||
+ 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 block tree preventing initiating an attack
|
||||
Fix return to title menu synchronization bug
|
||||
|
||||
@ -801,6 +801,11 @@ Migrate documentation
|
||||
Netcode generator qol fixes
|
||||
Combat Stances Component
|
||||
Remove geometry shader support
|
||||
Work on clustered lighting
|
||||
|
||||
(09/19/2024)
|
||||
Cluster lighting completed
|
||||
|
||||
|
||||
# TODO
|
||||
|
||||
@ -836,11 +841,15 @@ Code Generation
|
||||
|
||||
Rearchitecting
|
||||
- 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
|
||||
- Rename "BehaviorTree" to be "Component" (what it actually is)
|
||||
- Refactor ground movement components
|
||||
- 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:
|
||||
Transvoxel implementation
|
||||
|
||||
@ -232,6 +232,24 @@ public class CameraEntityUtils {
|
||||
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
|
||||
* @param entity The entity
|
||||
|
||||
@ -250,6 +250,7 @@ public class Globals {
|
||||
|
||||
public static float verticalFOV = 90;
|
||||
public static float aspectRatio = 2.0f;
|
||||
public static float nearClip = 0.001f;
|
||||
|
||||
//matrices for drawing models
|
||||
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/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
|
||||
//load them into memory now. The loading time penalty is worth it I think.
|
||||
Globals.assetManager.loadAssetsInQueue();
|
||||
|
||||
@ -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_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";
|
||||
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import electrosphere.renderer.buffer.HomogenousUniformBuffer;
|
||||
import electrosphere.renderer.loading.ModelLoader;
|
||||
import electrosphere.renderer.model.Mesh;
|
||||
import electrosphere.renderer.model.Model;
|
||||
import electrosphere.renderer.shader.ComputeShader;
|
||||
import electrosphere.renderer.shader.ShaderProgram;
|
||||
import electrosphere.renderer.texture.Texture;
|
||||
import electrosphere.renderer.texture.TextureMap;
|
||||
@ -20,6 +21,7 @@ import electrosphere.server.poseactor.PoseModel;
|
||||
import electrosphere.util.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
@ -51,6 +53,12 @@ public class AssetManager {
|
||||
Map<String,ShaderProgram> shadersLoadedIntoMemory = new ConcurrentHashMap<String,ShaderProgram>();
|
||||
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>();
|
||||
List<PhysicsMeshQueueItem> physicsMeshesToLoad = new CopyOnWriteArrayList<PhysicsMeshQueueItem>();
|
||||
|
||||
@ -126,6 +134,20 @@ public class AssetManager {
|
||||
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
|
||||
LoggerInterface.loggerEngine.DEBUG_LOOP("AssetManager - Load pose models");
|
||||
for(String currentPath: poseModelsInQueue){
|
||||
@ -415,6 +437,40 @@ public class AssetManager {
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@ import org.lwjgl.opengl.GL45;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.buffer.OpenGLBuffer;
|
||||
import electrosphere.renderer.buffer.UniformBlockBinding;
|
||||
import electrosphere.renderer.shader.Shader;
|
||||
import electrosphere.renderer.shader.ShaderProgram;
|
||||
@ -122,7 +123,7 @@ public class OpenGLState {
|
||||
* @return The viewport's dimensions
|
||||
*/
|
||||
public Vector2i getViewport(){
|
||||
return viewport;
|
||||
return new Vector2i(viewport);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -333,13 +334,13 @@ public class OpenGLState {
|
||||
if(currentBuffer == null || currentBuffer != buffer){
|
||||
//does not already contain index, should bind
|
||||
this.indexBlockMap.put(index,buffer);
|
||||
GL45.glBindBufferBase(index, index, buffer.getId());
|
||||
GL45.glBindBufferBase(OpenGLBuffer.getTypeInt(buffer), index, buffer.getId());
|
||||
Globals.renderingEngine.checkError();
|
||||
}
|
||||
} else {
|
||||
//does not already contain index, should bind
|
||||
this.indexBlockMap.put(index,buffer);
|
||||
GL45.glBindBufferBase(index, index, buffer.getId());
|
||||
GL45.glBindBufferBase(OpenGLBuffer.getTypeInt(buffer), index, buffer.getId());
|
||||
Globals.renderingEngine.checkError();
|
||||
}
|
||||
}
|
||||
@ -348,10 +349,10 @@ public class OpenGLState {
|
||||
* Unbinds a buffer from a given uniform buffer block index
|
||||
* @param index the index
|
||||
*/
|
||||
public void glUnbindBufferBase(int index){
|
||||
public void glUnbindBufferBase(int index, UniformBlockBinding buffer){
|
||||
if(this.indexBlockMap.containsKey(index)){
|
||||
this.indexBlockMap.remove(index);
|
||||
GL45.glBindBufferBase(index, index, UniformBlockBinding.UNBIND_ADDRESS);
|
||||
GL45.glBindBufferBase(OpenGLBuffer.getTypeInt(buffer), index, UniformBlockBinding.UNBIND_ADDRESS);
|
||||
Globals.renderingEngine.checkError();
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,7 +415,7 @@ public class RenderingEngine {
|
||||
|
||||
|
||||
//instantiate light manager
|
||||
lightManager = new LightManager();
|
||||
lightManager = LightManager.create();
|
||||
|
||||
//
|
||||
//Fog
|
||||
@ -452,8 +452,7 @@ public class RenderingEngine {
|
||||
verticalFOV = (float)(Globals.verticalFOV * Math.PI /180.0f);
|
||||
//set local aspect ratio and global aspect ratio at the same time
|
||||
aspectRatio = Globals.aspectRatio = Globals.WINDOW_WIDTH / (float)Globals.WINDOW_HEIGHT;
|
||||
float nearClip = 0.001f;
|
||||
Globals.projectionMatrix.setPerspective(verticalFOV, Globals.aspectRatio, nearClip, Globals.userSettings.getGraphicsViewDistance());
|
||||
Globals.projectionMatrix.setPerspective(verticalFOV, Globals.aspectRatio, Globals.nearClip, Globals.userSettings.getGraphicsViewDistance());
|
||||
Globals.viewMatrix.translation(new Vector3f(0.0f,0.0f,-3.0f));
|
||||
|
||||
/**
|
||||
@ -489,7 +488,7 @@ public class RenderingEngine {
|
||||
}
|
||||
|
||||
//Update light buffer
|
||||
lightManager.updateData();
|
||||
lightManager.update(renderPipelineState,openGLState,Globals.playerCamera);
|
||||
checkError();
|
||||
|
||||
|
||||
|
||||
@ -223,7 +223,7 @@ public class StridedInstanceData implements InstanceData {
|
||||
|
||||
@Override
|
||||
public void upload(OpenGLState openGLState, RenderPipelineState renderPipelineState){
|
||||
this.buffer.upload();
|
||||
this.buffer.upload(openGLState);
|
||||
openGLState.glBindBufferBase(0, buffer);
|
||||
}
|
||||
|
||||
|
||||
@ -4,9 +4,9 @@ import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL45;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.renderer.OpenGLState;
|
||||
import electrosphere.renderer.buffer.BufferEnums.BufferAccess;
|
||||
import electrosphere.renderer.buffer.BufferEnums.BufferUsage;
|
||||
|
||||
@ -40,7 +40,7 @@ public class ShaderStorageBuffer implements UniformBlockBinding {
|
||||
Globals.renderingEngine.checkError();
|
||||
GL45.glBindBuffer(GL45.GL_SHADER_STORAGE_BUFFER, id);
|
||||
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();
|
||||
GL45.glBindBuffer(GL45.GL_SHADER_STORAGE_BUFFER,id);
|
||||
Globals.renderingEngine.checkError();
|
||||
@ -51,19 +51,21 @@ public class ShaderStorageBuffer implements UniformBlockBinding {
|
||||
/**
|
||||
* Uploads the java side buffer to opengl
|
||||
*/
|
||||
public void upload(){
|
||||
public void upload(OpenGLState openGLState){
|
||||
long offset = 0;
|
||||
//bind
|
||||
GL45.glBindBuffer(GL45.GL_SHADER_STORAGE_BUFFER,id);
|
||||
Globals.renderingEngine.checkError();
|
||||
if(buffer.limit() > buffer.position()){
|
||||
//bind
|
||||
openGLState.glBindBufferBase(0, this);
|
||||
Globals.renderingEngine.checkError();
|
||||
|
||||
//upload
|
||||
GL45.glBufferSubData(GL45.GL_SHADER_STORAGE_BUFFER, offset, buffer);
|
||||
Globals.renderingEngine.checkError();
|
||||
|
||||
//unbind
|
||||
GL45.glBindBuffer(GL45.GL_SHADER_STORAGE_BUFFER,UNBIND_ADDRESS);
|
||||
Globals.renderingEngine.checkError();
|
||||
//upload
|
||||
GL45.glBufferSubData(OpenGLBuffer.getTypeInt(this), offset, buffer);
|
||||
Globals.renderingEngine.checkError();
|
||||
|
||||
//unbind
|
||||
openGLState.glUnbindBufferBase(0, this);
|
||||
Globals.renderingEngine.checkError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -10,64 +10,34 @@ public class DirectionalLight {
|
||||
//the direction of the light as a uniform vector
|
||||
Vector3f direction;
|
||||
|
||||
//the ambient color
|
||||
Vector3f ambient;
|
||||
//the diffuse color
|
||||
Vector3f diffuse;
|
||||
//the specular color
|
||||
Vector3f specular;
|
||||
//the color
|
||||
Vector3f color;
|
||||
|
||||
public void setDirection(Vector3f direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public void setAmbient(Vector3f ambient) {
|
||||
this.ambient = ambient;
|
||||
}
|
||||
|
||||
public void setDiffuse(Vector3f diffuse) {
|
||||
this.diffuse = diffuse;
|
||||
}
|
||||
|
||||
public void setSpecular(Vector3f specular) {
|
||||
this.specular = specular;
|
||||
public void setColor(Vector3f color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public Vector3f getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public Vector3f getAmbient() {
|
||||
return ambient;
|
||||
}
|
||||
|
||||
public Vector3f getDiffuse() {
|
||||
return diffuse;
|
||||
}
|
||||
|
||||
public Vector3f getSpecular() {
|
||||
return specular;
|
||||
public Vector3f getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public DirectionalLight(Vector3f direction){
|
||||
this.direction = direction;
|
||||
ambient = new Vector3f(0.05f, 0.05f, 0.05f);
|
||||
diffuse = new Vector3f(0.4f, 0.4f, 0.4f);
|
||||
specular = new Vector3f(0.5f, 0.5f, 0.5f);
|
||||
color = new Vector3f(1.0f);
|
||||
this.direction.normalize();
|
||||
ambient.normalize();
|
||||
diffuse.normalize();
|
||||
specular.normalize();
|
||||
}
|
||||
|
||||
public DirectionalLight(Vector3f direction, Vector3f color){
|
||||
this.direction = direction;
|
||||
ambient = new Vector3f( color.x * 0.05f, color.y * 0.05f, color.z * 0.05f);
|
||||
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.color = new Vector3f(color);
|
||||
this.direction.normalize();
|
||||
ambient.normalize();
|
||||
diffuse.normalize();
|
||||
specular.normalize();
|
||||
}
|
||||
}
|
||||
@ -1,300 +1,339 @@
|
||||
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.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Vector3f;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
import org.joml.Vector3i;
|
||||
|
||||
import electrosphere.client.entity.camera.CameraEntityUtils;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.engine.assetmanager.AssetDataStrings;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityCreationUtils;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.OpenGLState;
|
||||
import electrosphere.renderer.RenderingEngine;
|
||||
import electrosphere.renderer.shader.ShaderProgram;
|
||||
import electrosphere.renderer.RenderPipelineState;
|
||||
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
|
||||
*/
|
||||
public class LightManager {
|
||||
|
||||
/**
|
||||
* Maximum number of lights per cluster
|
||||
*/
|
||||
static final int MAX_LIGHTS_PER_CLUSTER = 100;
|
||||
|
||||
/**
|
||||
* Size of the light cluster structure
|
||||
*/
|
||||
static final int CLUSTER_STRUCT_SIZE = 16 + 16 + 4 + (4 * MAX_LIGHTS_PER_CLUSTER);
|
||||
|
||||
/**
|
||||
* The width of the light cluster grid's x dimension
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* The size of a single point light struct
|
||||
*/
|
||||
static final int POINT_LIGHT_STRUCT_SIZE = 16 + 16 + 4 + 4 + 4 + 4;
|
||||
|
||||
/**
|
||||
* The maximum number of point lights
|
||||
*/
|
||||
static final int MAX_POINT_LIGHTS = 2048;
|
||||
|
||||
/**
|
||||
* The size of the point light buffer
|
||||
*/
|
||||
static final int POINT_LIGHT_BUFFER_SIZE = POINT_LIGHT_STRUCT_SIZE * MAX_POINT_LIGHTS;
|
||||
|
||||
/**
|
||||
* The number of "threads" to run for light culling
|
||||
*/
|
||||
static final int CULL_LOCAL_SIZE = 128;
|
||||
|
||||
/**
|
||||
* The number of work groups to dispatch for the light culling phase
|
||||
* !!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
|
||||
|
||||
final static int BIND_POINT = 1;
|
||||
final static int POINT_LIGHT_COUNT = 10;
|
||||
final static int BUFFER_SIZE = 1184;
|
||||
int uboIndex;
|
||||
ByteBuffer dataBuffer;
|
||||
|
||||
//sun position (For shadow maps)
|
||||
Vector3f sunPosition = new Vector3f(0.2f,-1.0f,0.3f);
|
||||
|
||||
//lights
|
||||
DirectionalLight directionalLight;
|
||||
PointLight[] pointLights;
|
||||
|
||||
public LightManager(){
|
||||
|
||||
//create data buffer
|
||||
dataBuffer = BufferUtils.createByteBuffer(BUFFER_SIZE);
|
||||
|
||||
uboIndex = glGenBuffers();
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, uboIndex);
|
||||
glBufferData(GL_UNIFORM_BUFFER, BUFFER_SIZE, GL_DYNAMIC_DRAW); // allocate 152 bytes of memory
|
||||
//set range to full size
|
||||
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());
|
||||
directionalLight.setAmbient(new Vector3f(0.6f,0.6f,0.6f));
|
||||
directionalLight.setDiffuse(new Vector3f(0.3f,0.3f,0.3f));
|
||||
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++){
|
||||
pointLights[i] = new PointLight(new Vector3f(0,0,0),new Vector3f(0,0,0));
|
||||
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);
|
||||
// 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));
|
||||
*/
|
||||
ShaderStorageBuffer pointLightSSBO;
|
||||
|
||||
|
||||
/**
|
||||
* The direct light ssbo
|
||||
*
|
||||
struct DirectLight {
|
||||
vec3 direction; //12 bytes
|
||||
vec3 color; //12 bytes
|
||||
};
|
||||
*/
|
||||
ShaderStorageBuffer dirLightSSBO;
|
||||
|
||||
/**
|
||||
* The directional light
|
||||
*/
|
||||
DirectionalLight directionalLight;
|
||||
|
||||
|
||||
/*
|
||||
Vector3f lightLoc = new Vector3f(0.2f,-1.0f,0.3f);
|
||||
float temp[] = new float[3];
|
||||
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;
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private LightManager(){
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the directional light for this light manager
|
||||
* @return the directional light
|
||||
* Creates a light manager
|
||||
* @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(){
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -10,9 +10,8 @@ public class PointLight {
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
Vector3f ambient;
|
||||
Vector3f diffuse;
|
||||
Vector3f specular;
|
||||
float radius;
|
||||
Vector3f color;
|
||||
|
||||
public void setPosition(Vector3f position) {
|
||||
this.position = position;
|
||||
@ -30,16 +29,12 @@ public class PointLight {
|
||||
this.quadratic = quadratic;
|
||||
}
|
||||
|
||||
public void setAmbient(Vector3f ambient) {
|
||||
this.ambient = ambient;
|
||||
public void setRadius(float radius){
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
public void setDiffuse(Vector3f diffuse) {
|
||||
this.diffuse = diffuse;
|
||||
}
|
||||
|
||||
public void setSpecular(Vector3f specular) {
|
||||
this.specular = specular;
|
||||
public void setColor(Vector3f color){
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public Vector3f getPosition() {
|
||||
@ -58,43 +53,29 @@ public class PointLight {
|
||||
return quadratic;
|
||||
}
|
||||
|
||||
public Vector3f getAmbient() {
|
||||
return ambient;
|
||||
public Vector3f getColor(){
|
||||
return color;
|
||||
}
|
||||
|
||||
public Vector3f getDiffuse() {
|
||||
return diffuse;
|
||||
}
|
||||
|
||||
public Vector3f getSpecular() {
|
||||
return specular;
|
||||
public float getRadius(){
|
||||
return radius;
|
||||
}
|
||||
|
||||
public PointLight(Vector3f position){
|
||||
this.position = position;
|
||||
radius = 1;
|
||||
constant = 1.0f;
|
||||
linear = 0.01f;
|
||||
quadratic = 0.01f;
|
||||
ambient = new Vector3f(0.05f, 0.05f, 0.05f);
|
||||
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();
|
||||
linear = 0.7f;
|
||||
quadratic = 1.8f;
|
||||
color = new Vector3f(1.0f);
|
||||
}
|
||||
|
||||
public PointLight(Vector3f position, Vector3f color){
|
||||
this.position = position;
|
||||
radius = 1;
|
||||
constant = 1.0f;
|
||||
linear = 0.01f;
|
||||
quadratic = 0.01f;
|
||||
ambient = new Vector3f(color.x * 0.05f, color.y * 0.05f, color.z * 0.05f);
|
||||
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();
|
||||
linear = 0.7f;
|
||||
quadratic = 1.8f;
|
||||
this.color = color;
|
||||
}
|
||||
}
|
||||
@ -21,6 +21,7 @@ import org.joml.Matrix4d;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Sphered;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3i;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
@ -354,7 +355,16 @@ public class Mesh {
|
||||
//don't buffer as the light manager hasn't initialized
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
|
||||
@ -5,7 +5,11 @@ import java.util.Map;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector2d;
|
||||
import org.joml.Vector2i;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3i;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL40;
|
||||
import org.lwjgl.opengl.GL45;
|
||||
@ -20,6 +24,11 @@ import electrosphere.renderer.RenderingEngine;
|
||||
* A compute shader program (leaving object called "ComputeShader" because that's how most people refer to them)
|
||||
*/
|
||||
public class ComputeShader implements Shader {
|
||||
|
||||
/**
|
||||
* The default local size
|
||||
*/
|
||||
public static final int DEFAULT_LOCAL_SIZE = 1;
|
||||
|
||||
/**
|
||||
* The id for the shader
|
||||
@ -86,14 +95,7 @@ public class ComputeShader implements Shader {
|
||||
*/
|
||||
public void dispatch(int x, int y, int z){
|
||||
GL45.glDispatchCompute(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the memory barrier value
|
||||
* @param value The value
|
||||
*/
|
||||
public void memoryBarier(int value){
|
||||
GL45.glMemoryBarrier(value);
|
||||
Globals.renderingEngine.checkError();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -164,7 +166,39 @@ public class ComputeShader implements Shader {
|
||||
Vector3f currentUniform = (Vector3f)value;
|
||||
GL40.glUniform3fv(uniformLocation, currentUniform.get(BufferUtils.createFloatBuffer(3)));
|
||||
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
|
||||
|
||||
@ -2,6 +2,8 @@ package electrosphere.renderer.shader;
|
||||
|
||||
import org.lwjgl.opengl.GL45;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public static void glMemoryBarrier(Barrier barrier){
|
||||
@ -205,6 +209,7 @@ public class MemoryBarrier {
|
||||
} break;
|
||||
}
|
||||
GL45.glMemoryBarrier(barrierVal);
|
||||
Globals.renderingEngine.checkError();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -29,7 +29,11 @@ import javax.management.RuntimeErrorException;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector2d;
|
||||
import org.joml.Vector2i;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3i;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL40;
|
||||
@ -704,6 +708,38 @@ public class ShaderProgram implements Shader {
|
||||
Globals.renderingEngine.checkError();
|
||||
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
|
||||
} else if(value instanceof Integer){
|
||||
|
||||
@ -48,7 +48,7 @@ public class ShaderStorageBufferTests extends RenderingTestTemplate {
|
||||
public void test_upload_NoThrow(){
|
||||
assertDoesNotThrow(() -> {
|
||||
ShaderStorageBuffer buffer = new ShaderStorageBuffer(10, BufferUsage.STATIC, BufferAccess.READ);
|
||||
buffer.upload();
|
||||
buffer.upload(Globals.renderingEngine.getOpenGLState());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user