Skip to content

Commit

Permalink
pointlight: Implement point light.
Browse files Browse the repository at this point in the history
  • Loading branch information
vlj committed Dec 30, 2023
1 parent ec451ba commit 11f0808
Show file tree
Hide file tree
Showing 37 changed files with 782 additions and 100 deletions.
51 changes: 51 additions & 0 deletions data/base/shaders/pointlights.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#define WZ_MAX_POINT_LIGHTS 0
#define WZ_MAX_INDEXED_POINT_LIGHTS 0
#define WZ_BUCKED_DIMENSION 0

uniform vec4 PointLightsPosition[WZ_MAX_POINT_LIGHTS];
uniform vec4 PointLightsColorAndEnergy[WZ_MAX_POINT_LIGHTS];
uniform ivec4 bucketOffsetAndSize[WZ_BUCKED_DIMENSION * WZ_BUCKED_DIMENSION];
uniform ivec4 PointLightsIndex[WZ_MAX_INDEXED_POINT_LIGHTS];
uniform float viewportWidth;
uniform float viewportHeight;

// See https://lisyarus.github.io/blog/graphics/2022/07/30/point-light-attenuation.html for explanation
// we want something that looks somewhat physically correct, but must absolutely be 0 past range
float pointLightEnergyAtPosition(vec3 position, vec3 pointLightWorldPosition, float range)
{
vec3 pointLightVector = position - pointLightWorldPosition;
float normalizedDistance = length(pointLightVector) / range;

float sqNormDist = normalizedDistance * normalizedDistance;
float numerator = max(1 - sqNormDist, 0);
return numerator * numerator / ( 1 + 2 * sqNormDist);
}

vec4 processPointLight(vec3 WorldFragPos, vec3 fragNormal, vec3 viewVector, vec4 albedo, float gloss, vec3 pointLightWorldPosition, float pointLightEnergy, vec3 pointLightColor, mat3 normalWorldSpaceToLocalSpace)
{
vec3 pointLightVector = WorldFragPos - pointLightWorldPosition;
vec3 pointLightDir = -normalize(pointLightVector * normalWorldSpaceToLocalSpace);

float energy = pointLightEnergyAtPosition(WorldFragPos, pointLightWorldPosition, pointLightEnergy);
vec4 lightColor = vec4(pointLightColor * energy, 1);

float pointLightLambert = max(dot(fragNormal, pointLightDir), 0.0);

vec3 pointLightHalfVec = normalize(viewVector + pointLightDir);

float pointLightBlinn = pow(clamp(dot(fragNormal, pointLightHalfVec), 0.f, 1.f), 16.f);
return lightColor * pointLightLambert * (albedo + pointLightBlinn * (gloss * gloss));
}

// Unused for now
// vec4 processPointLightScattering(vec3 pointLightWorldPosition, float pointLightEnergy, vec4 pointLightColor)
// {
// // manual integration
// vec3 viewLine = fragPos - cameraPos.xyz;
// vec3 result = vec3(0);
// for (int i = 0; i < 10; i++)
// {
// result += pointLightEnergyAtPosition(fragPos + i * viewLine / 10, pointLightWorldPosition, pointLightEnergy) / 10;
// }
// return vec4(result * pointLightColor.xyz * fogColor.xyz, 1);
// }
25 changes: 24 additions & 1 deletion data/base/shaders/tcmask_instanced.frag
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ out vec4 FragColor;
// Uses gl_FragColor
#endif


#include "pointlights.frag"

float getShadowMapDepthComp(vec2 base_uv, float u, float v, vec2 shadowMapSizeInv, int cascadeIndex, float z)
{
vec2 uv = base_uv + vec2(u, v) * shadowMapSizeInv;
Expand Down Expand Up @@ -337,13 +340,15 @@ void main()
float distanceAboveTerrain = uvLightmap.z;
float lightmapFactor = 1.0f - (clamp(distanceAboveTerrain, 0.f, 300.f) / 300.f);

float specularMapValue = 0;

if (lambertTerm > 0.0)
{
float vanillaFactor = 0.0; // Classic models shouldn't use diffuse light

if (specularmap != 0)
{
float specularMapValue = texture(TextureSpecular, texCoord, WZ_MIP_LOAD_BIAS).r;
specularMapValue = texture(TextureSpecular, texCoord, WZ_MIP_LOAD_BIAS).r;
vec4 specularFromMap = vec4(specularMapValue, specularMapValue, specularMapValue, 1.0);

// Gaussian specular term computation
Expand All @@ -361,6 +366,24 @@ void main()
// ambient light maxed for classic models to keep results similar to original
light += vec4(blendAddEffectLighting(ambient.rgb, ((lightmap_vec4.rgb * lightmapFactor) / 3.f)), ambient.a) * diffuseMap * (1.0 + (1.0 - float(specularmap)));

vec2 clipSpaceCoord = gl_FragCoord.xy / vec2(viewportWidth, viewportHeight);
ivec2 bucket = ivec2(8 * clipSpaceCoord);
int bucketId = min(bucket.y + bucket.x * 8 , WZ_BUCKED_DIMENSION * WZ_BUCKED_DIMENSION - 1);

for (int i = 0; i < bucketOffsetAndSize[bucketId].y; i++)
{
int lightIndex = bucketOffsetAndSize[bucketId].x + i;
vec4 position = PointLightsPosition[PointLightsIndex[lightIndex].x];
vec4 colorAndEnergy = PointLightsColorAndEnergy[PointLightsIndex[lightIndex].x];
vec3 tmp = position.xyz * vec3(1., 1., -1.);
mat3 identityMat = mat3(
1., 0., 0.,
0., 1., 0.,
0., 0., 1.
);
light += processPointLight(fragPos, -N, normalize(halfVec - lightDir), diffuse, specularMapValue, tmp, colorAndEnergy.w, colorAndEnergy.xyz, identityMat);
}

light.rgb *= visibility;
light.a = 1.0f;

Expand Down
4 changes: 3 additions & 1 deletion data/base/shaders/terrain_combined.vert
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ out vec4 fgroundWeights;
out vec3 groundLightDir;
out vec3 groundHalfVec;
out mat2 decal2groundMat2;

out mat3 ModelTangentMatrix;
// for Shadows
out vec3 fragPos;
out vec3 fragNormal;
Expand All @@ -55,7 +57,7 @@ void main()
vec3 vaxis = vec3(1,0,0); // v ~ vertex.x, see uv_ground
vec3 tangent = normalize(cross(vertexNormal, vaxis));
vec3 bitangent = cross(vertexNormal, tangent);
mat3 ModelTangentMatrix = mat3(tangent, bitangent, vertexNormal); // aka TBN-matrix
ModelTangentMatrix = mat3(tangent, bitangent, vertexNormal); // aka TBN-matrix
// transform light to TangentSpace:
vec3 eyeVec = normalize((cameraPos.xyz - vertex.xyz) * ModelTangentMatrix);
groundLightDir = sunPos.xyz * ModelTangentMatrix; // already normalized
Expand Down
20 changes: 20 additions & 0 deletions data/base/shaders/terrain_combined_high.frag
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ uniform vec4 ambientLight;
uniform vec4 diffuseLight;
uniform vec4 specularLight;


uniform vec4 cameraPos; // in modelSpace
uniform vec4 sunPos; // in modelSpace, normalized

// fog
Expand All @@ -77,6 +79,9 @@ in vec4 fgroundWeights;
in vec3 groundLightDir;
in vec3 groundHalfVec;
in mat2 decal2groundMat2;


in mat3 ModelTangentMatrix;
// For Shadows
in vec3 fragPos;
in vec3 fragNormal;
Expand All @@ -88,6 +93,7 @@ out vec4 FragColor;
#endif

#include "terrain_combined_frag.glsl"
#include "pointlights.frag"

vec3 getGroundUv(int i) {
uint groundNo = fgrounds[i];
Expand Down Expand Up @@ -141,6 +147,20 @@ vec4 doBumpMapping(BumpData b, vec3 lightDir, vec3 halfVec) {

vec4 res = (b.color*light) + light_spec;

vec2 clipSpaceCoord = gl_FragCoord.xy / vec2(viewportWidth, viewportHeight);
ivec2 bucket = ivec2(8 * clipSpaceCoord);
int bucketId = min(bucket.y + bucket.x * 8, WZ_BUCKED_DIMENSION * WZ_BUCKED_DIMENSION - 1);

for (int i = 0; i < bucketOffsetAndSize[bucketId].y; i++)
{
int lightIndex = bucketOffsetAndSize[bucketId].x + i;
vec4 position = PointLightsPosition[PointLightsIndex[lightIndex].x];
vec4 colorAndEnergy = PointLightsColorAndEnergy[PointLightsIndex[lightIndex].x];
vec3 tmp = position.xyz * vec3(1., 1., -1.);
res += processPointLight(fragPos, b.N, normalize(halfVec + lightDir), b.color, b.gloss, tmp, colorAndEnergy.w, colorAndEnergy.xyz, ModelTangentMatrix);
}


return vec4(res.rgb, b.color.a);
}

Expand Down
40 changes: 40 additions & 0 deletions data/base/shaders/vk/pointlights.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// See https://lisyarus.github.io/blog/graphics/2022/07/30/point-light-attenuation.html for explanation
// we want something that looks somewhat physically correct, but must absolutely be 0 past range
float pointLightEnergyAtPosition(vec3 position, vec3 pointLightWorldPosition, float range)
{
vec3 pointLightVector = position - pointLightWorldPosition;
float normalizedDistance = length(pointLightVector) / range;

float sqNormDist = normalizedDistance * normalizedDistance;
float numerator = max(1 - sqNormDist, 0);
return numerator * numerator / ( 1 + 2 * sqNormDist);
}

vec4 processPointLight(vec3 WorldFragPos, vec3 fragNormal, vec3 viewVector, vec4 albedo, float gloss, vec3 pointLightWorldPosition, float pointLightEnergy, vec3 pointLightColor, mat3 normalWorldSpaceToLocalSpace)
{
vec3 pointLightVector = WorldFragPos - pointLightWorldPosition;
vec3 pointLightDir = -normalize(pointLightVector * normalWorldSpaceToLocalSpace);

float energy = pointLightEnergyAtPosition(WorldFragPos, pointLightWorldPosition, pointLightEnergy);
vec4 lightColor = vec4(pointLightColor * energy, 1);

float pointLightLambert = max(dot(fragNormal, pointLightDir), 0.0);

vec3 pointLightHalfVec = normalize(viewVector + pointLightDir);

float pointLightBlinn = pow(clamp(dot(fragNormal, pointLightHalfVec), 0.f, 1.f), 16.f);
return lightColor * pointLightLambert * (albedo + pointLightBlinn * (gloss * gloss));
}

// Unused for now
// vec4 processPointLightScattering(vec3 pointLightWorldPosition, float pointLightEnergy, vec4 pointLightColor)
// {
// // manual integration
// vec3 viewLine = fragPos - cameraPos.xyz;
// vec3 result = vec3(0);
// for (int i = 0; i < 10; i++)
// {
// result += pointLightEnergyAtPosition(fragPos + i * viewLine / 10, pointLightWorldPosition, pointLightEnergy) / 10;
// }
// return vec4(result * pointLightColor.xyz * fogColor.xyz, 1);
// }
23 changes: 22 additions & 1 deletion data/base/shaders/vk/tcmask_instanced.frag
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ layout(location = 12) in vec3 fragPos;

layout(location = 0) out vec4 FragColor;

#include "pointLights.glsl"

float getShadowMapDepthComp(vec2 base_uv, float u, float v, vec2 shadowMapSizeInv, int cascadeIndex, float z)
{
vec2 uv = base_uv + vec2(u, v) * shadowMapSizeInv;
Expand Down Expand Up @@ -307,13 +309,14 @@ void main()
float distanceAboveTerrain = uvLightmap.z;
float lightmapFactor = 1.0f - (clamp(distanceAboveTerrain, 0.f, 300.f) / 300.f);

float specularMapValue = 0;
if (lambertTerm > 0.0)
{
float vanillaFactor = 0.0; // Classic models shouldn't use diffuse light

if (specularmap != 0)
{
float specularMapValue = texture(TextureSpecular, texCoord, WZ_MIP_LOAD_BIAS).r;
specularMapValue = texture(TextureSpecular, texCoord, WZ_MIP_LOAD_BIAS).r;
vec4 specularFromMap = vec4(specularMapValue, specularMapValue, specularMapValue, 1.0);

// Gaussian specular term computation
Expand All @@ -331,6 +334,24 @@ void main()
// ambient light maxed for classic models to keep results similar to original
light += vec4(blendAddEffectLighting(ambient.rgb, ((lightmap_vec4.rgb * lightmapFactor) / 3.f)), ambient.a) * diffuseMap * (1.0 + (1.0 - float(specularmap)));

vec2 clipSpaceCoord = gl_FragCoord.xy / vec2(viewportWidth, viewportHeight);
ivec2 bucket = ivec2(8 * clipSpaceCoord);
int bucketId = min(bucket.y + bucket.x * 8 , WZ_BUCKED_DIMENSION * WZ_BUCKED_DIMENSION - 1);

for (int i = 0; i < bucketOffsetAndSize[bucketId].y; i++)
{
mat3 identityMat = mat3(
1., 0., 0.,
0., 1., 0.,
0., 0., 1.
);
int lightIndex = bucketOffsetAndSize[bucketId].x + i;
vec4 position = PointLightsPosition[PointLightsIndex[lightIndex].x];
vec4 colorAndEnergy = PointLightsColorAndEnergy[PointLightsIndex[lightIndex].x];
vec3 tmp = position.xyz * vec3(1., 1., -1.);
light += processPointLight(fragPos, -N, normalize(halfVec - lightDir), diffuse, specularMapValue, tmp, colorAndEnergy.w, colorAndEnergy.xyz, identityMat);
}

light.rgb *= visibility;
light.a = 1.0f;

Expand Down
11 changes: 11 additions & 0 deletions data/base/shaders/vk/tcmask_instanced.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

#define WZ_MAX_SHADOW_CASCADES 3

#define WZ_MAX_POINT_LIGHTS 128
#define WZ_MAX_INDEXED_POINT_LIGHTS 512
#define WZ_BUCKED_DIMENSION 8

layout(std140, set = 0, binding = 0) uniform globaluniforms
{
mat4 ProjectionMatrix;
Expand All @@ -20,6 +24,13 @@ layout(std140, set = 0, binding = 0) uniform globaluniforms
float fogStart;
float graphicsCycle;
int fogEnabled;
int viewportWidth;
int viewportHeight;

vec4 PointLightsPosition[WZ_MAX_POINT_LIGHTS];
vec4 PointLightsColorAndEnergy[WZ_MAX_POINT_LIGHTS];
ivec4 bucketOffsetAndSize[WZ_BUCKED_DIMENSION * WZ_BUCKED_DIMENSION];
ivec4 PointLightsIndex[WZ_MAX_INDEXED_POINT_LIGHTS];
};

layout(std140, set = 1, binding = 0) uniform meshuniforms
Expand Down
11 changes: 11 additions & 0 deletions data/base/shaders/vk/terrain_combined.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

#define WZ_MAX_SHADOW_CASCADES 3

#define WZ_MAX_POINT_LIGHTS 128
#define WZ_MAX_INDEXED_POINT_LIGHTS 512
#define WZ_BUCKED_DIMENSION 8


layout(std140, set = 0, binding = 0) uniform cbuffer {
mat4 ModelViewProjectionMatrix;
mat4 ViewMatrix;
Expand All @@ -21,6 +26,12 @@ layout(std140, set = 0, binding = 0) uniform cbuffer {
float fogEnd;
float fogStart;
int quality;
int viewportWidth;
int viewportHeight;
vec4 PointLightsPosition[WZ_MAX_POINT_LIGHTS];
vec4 PointLightsColorAndEnergy[WZ_MAX_POINT_LIGHTS];
ivec4 bucketOffsetAndSize[WZ_BUCKED_DIMENSION * WZ_BUCKED_DIMENSION];
ivec4 PointLightsIndex[WZ_MAX_INDEXED_POINT_LIGHTS];
};

// interpolated data. location count = 11
Expand Down
3 changes: 2 additions & 1 deletion data/base/shaders/vk/terrain_combined.vert
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ layout(location = 7) in vec4 groundWeights; // ground weights for splatting

layout(location = 0) out FragData frag;
layout(location = 11) out flat FragFlatData fragf;
layout(location = 14) out mat3 ModelTangentMatrix;

void main()
{
Expand All @@ -33,7 +34,7 @@ void main()
vec3 vaxis = vec3(1,0,0); // v ~ vertex.x, see uv_ground
vec3 tangent = normalize(cross(vertexNormal, vaxis));
vec3 bitangent = cross(vertexNormal, tangent);
mat3 ModelTangentMatrix = mat3(tangent, bitangent, vertexNormal); // aka TBN-matrix
ModelTangentMatrix = mat3(tangent, bitangent, vertexNormal); // aka TBN-matrix
// transform light to TangentSpace:
vec3 eyeVec = normalize((cameraPos.xyz - vertex.xyz) * ModelTangentMatrix);
frag.groundLightDir = sunPos.xyz * ModelTangentMatrix; // already normalized
Expand Down
15 changes: 15 additions & 0 deletions data/base/shaders/vk/terrain_combined_high.frag
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ layout(set = 1, binding = 9) uniform sampler2DArrayShadow shadowMap;

layout(location = 0) in FragData frag;
layout(location = 11) flat in FragFlatData fragf;
layout(location = 14) in mat3 ModelTangentMatrix;

layout(location = 0) out vec4 FragColor;

#include "terrain_combined_frag.glsl"
#include "pointLights.glsl"

vec3 getGroundUv(int i) {
uint groundNo = fragf.grounds[i];
Expand Down Expand Up @@ -83,6 +85,19 @@ vec4 doBumpMapping(BumpData b, vec3 lightDir, vec3 halfVec) {

vec4 res = (b.color*light) + light_spec;

vec2 clipSpaceCoord = gl_FragCoord.xy / vec2(viewportWidth, viewportHeight);
ivec2 bucket = ivec2(8 * clipSpaceCoord);
int bucketId = min(bucket.y + bucket.x * 8 , WZ_BUCKED_DIMENSION * WZ_BUCKED_DIMENSION - 1);

for (int i = 0; i < bucketOffsetAndSize[bucketId].y; i++)
{
int lightIndex = bucketOffsetAndSize[bucketId].x + i;
vec4 position = PointLightsPosition[PointLightsIndex[lightIndex].x];
vec4 colorAndEnergy = PointLightsColorAndEnergy[PointLightsIndex[lightIndex].x];
vec3 tmp = position.xyz * vec3(1., 1., -1.);
res += processPointLight(frag.fragPos, b.N, normalize(halfVec + lightDir), b.color, b.gloss, tmp, colorAndEnergy.w, colorAndEnergy.xyz, ModelTangentMatrix);
}

return vec4(res.rgb, b.color.a);
}

Expand Down
4 changes: 2 additions & 2 deletions lib/framework/string_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
# endif
# if defined(DEBUG)
# define strdup(s) \
strdup2(s,__FILE__,__LINE__)
static inline char *strdup2(const char *s, char *fileName, int line)
strdup2(static_cast<const char*>(s),__LINE__)
static inline char *strdup2(const char *s, int line)
{
char *result;

Expand Down
Loading

0 comments on commit 11f0808

Please sign in to comment.