Archived
1
Fork 0
This repository has been archived on 2025-04-12. You can view files and clone it, but cannot push or open issues or pull requests.
prism/engine/base/shaders/rendering.nocompile.glsl
Joshua Goins ca2c2c9d3d Move all engine-specific models, materials etc. to a new base directory
This is a huge change, and basically breaks everything (as per usual!)

First of, this includes stuff like shaders so anything involving those
are broken and then fixed. A new BuildAssets cmake file is added to
aid in running AssetCompiler, and it seems to work fine on the engine
base assets.

The File API will eventually be revamped to handle this new way of
organizing the files and domains will eventually be gotten rid of all
together since I probably will replace it with game directory
priorities. As it stands right now, there isn't a way to easily
replace say - render_options.cfg with your own game-specific version.

Apple builds are probably broken by this commit (since I'm moving
around content and shader directories) to be fixed later.
2022-05-21 18:28:48 -04:00

312 lines
9.9 KiB
GLSL

struct ComputedSurfaceInfo {
vec3 N;
vec3 V;
vec3 F0, diffuse_color;
float NdotV;
float roughness, metallic;
};
ComputedSurfaceInfo compute_surface(const vec3 diffuse, const vec3 normal, const float metallic, const float roughness) {
ComputedSurfaceInfo info;
info.N = normalize(normal);
info.V = normalize(scene.camPos.xyz - in_frag_pos);
info.NdotV = max(dot(info.N, info.V), 0.0);
info.metallic = metallic;
info.roughness = max(0.0001, roughness);
info.F0 = 0.16 * (1.0 - info.metallic) + diffuse * info.metallic;
info.diffuse_color = (1.0 - info.metallic) * diffuse;
return info;
}
struct SurfaceBRDF {
vec3 diffuse, specular;
float NdotL;
};
SurfaceBRDF brdf(const vec3 L, const ComputedSurfaceInfo surface_info) {
SurfaceBRDF info;
// half-vector
const vec3 H = normalize(surface_info.V + L);
// fresnel reflectance function
const vec3 F = fresnel_schlick(surface_info.NdotV, surface_info.F0);
// geometry function
const float D = ggx_distribution(surface_info.N, H, surface_info.roughness);
// normal distribution function
const float G = geometry_smith(surface_info.N, surface_info.V, L, surface_info.roughness);
const vec3 numerator = F * G * D;
const float denominator = 4.0 * surface_info.NdotV * clamp(dot(surface_info.N, L), 0.0, 1.0);
// cook-torrance specular brdf
info.specular = numerator / (denominator + 0.001);
// lambertian diffuse
info.diffuse = surface_info.diffuse_color * (1.0 / PI);
info.NdotL = clamp(dot(surface_info.N, L), 0.0, 1.0);
return info;
}
struct ComputedLightInformation {
vec3 direction;
float radiance;
};
float pcf_sun(const vec4 shadowCoords, const float uvRadius) {
float sum = 0;
for(int i = 0; i < 16; i++) {
const float z = texture(sun_shadow, shadowCoords.xy + PoissionPCFDisk[i] * uvRadius).r;
sum += (z < (shadowCoords.z - 0.005)) ? 0.0 : 1.0;
}
return sum / 16;
}
#ifdef SHADOW_FILTER_PCSS
float search_width(const float uvLightSize, const float receiverDistance) {
return uvLightSize * (receiverDistance - 0.1f) / receiverDistance;
}
float penumbra_size(const float zReceiver, const float zBlocker) {
return (zReceiver - zBlocker) / zBlocker;
}
const int numBlockerSearchSamples = 16;
void blocker_distance_sun(const vec3 shadowCoords, const float uvLightSize, inout float avgBlockerDistance, inout int blockers) {
const float searchWidth = search_width(uvLightSize, shadowCoords.z);
float blockerSum = 0.0;
blockers = 0;
for(int i = 0; i < numBlockerSearchSamples; i++) {
const float z = texture(sun_shadow, shadowCoords.xy + PoissionPCFDisk[i] * searchWidth).r;
if(z < shadowCoords.z) {
blockerSum += z;
blockers++;
}
}
avgBlockerDistance = blockerSum / blockers;
}
float pcss_sun(const vec4 shadowCoords, float light_size_uv) {
float average_blocker_depth = 0.0;
int num_blockers = 0;
blocker_distance_sun(shadowCoords.xyz, light_size_uv, average_blocker_depth, num_blockers);
if(num_blockers < 1)
return 1.0;
const float penumbraWidth = penumbra_size(shadowCoords.z, average_blocker_depth);
const float uvRadius = penumbraWidth * light_size_uv * 0.1 / shadowCoords.z;
return pcf_sun(shadowCoords, uvRadius);
}
#endif
ComputedLightInformation calculate_sun(Light light) {
ComputedLightInformation light_info;
light_info.direction = normalize(light.positionType.xyz - vec3(0));
float shadow = 1.0;
if(light.shadowsEnable.x == 1.0) {
const vec4 shadowCoords = fragPosLightSpace / fragPosLightSpace.w;
if(shadowCoords.z > -1.0 && shadowCoords.z < 1.0) {
#ifdef SHADOW_FILTER_NONE
shadow = (texture(sun_shadow, shadowCoords.xy).r < shadowCoords.z - 0.005) ? 0.0 : 1.0;
#endif
#ifdef SHADOW_FILTER_PCF
shadow = pcf_sun(shadowCoords, 0.1);
#endif
#ifdef SHADOW_FILTER_PCSS
shadow = pcss_sun(shadowCoords, light.shadowsEnable.y);
#endif
}
}
light_info.radiance = light.directionPower.w * shadow;
return light_info;
}
float pcf_spot(const vec4 shadowCoords, const int index, const float uvRadius) {
float sum = 0;
for(int i = 0; i < 16; i++) {
const float z = texture(spot_shadow, vec3(shadowCoords.xy + PoissionPCFDisk[i] * uvRadius, index)).r;
sum += (z < (shadowCoords.z - 0.001)) ? 0.0 : 1.0;
}
return sum / 16;
}
#ifdef SHADOW_FILTER_PCSS
void blocker_distance_spot(const vec3 shadowCoords, const int index, const float uvLightSize, inout float avgBlockerDistance, inout int blockers) {
const float searchWidth = search_width(uvLightSize, shadowCoords.z);
float blockerSum = 0.0;
blockers = 0;
for(int i = 0; i < numBlockerSearchSamples; i++) {
const float z = texture(spot_shadow, vec3(shadowCoords.xy + PoissionPCFDisk[i] * searchWidth, index)).r;
if(z < shadowCoords.z) {
blockerSum += z;
blockers++;
}
}
avgBlockerDistance = blockerSum / blockers;
}
float pcss_spot(const vec4 shadowCoords, const int index, float light_size_uv) {
float average_blocker_depth = 0.0;
int num_blockers = 0;
blocker_distance_spot(shadowCoords.xyz, index, light_size_uv, average_blocker_depth, num_blockers);
if(num_blockers < 1)
return 1.0;
const float penumbraWidth = penumbra_size(-shadowCoords.z, average_blocker_depth);
const float uvRadius = penumbraWidth * light_size_uv * 0.1 / shadowCoords.z;
return pcf_spot(shadowCoords, index, uvRadius);
}
#endif
int last_spot_light = 0;
ComputedLightInformation calculate_spot(Light light) {
ComputedLightInformation light_info;
light_info.direction = normalize(light.positionType.xyz - in_frag_pos);
float shadow = 1.0;
if(light.shadowsEnable.x == 1.0) {
const vec4 shadowCoord = fragPostSpotLightSpace[last_spot_light] / fragPostSpotLightSpace[last_spot_light].w;
#ifdef SHADOW_FILTER_NONE
shadow = (texture(spot_shadow, vec3(shadowCoord.xy, last_spot_light)).r < shadowCoord.z - 0.005) ? 0.0 : 1.0;
#endif
#ifdef SHADOW_FILTER_PCF
shadow = pcf_spot(shadowCoord, last_spot_light, 0.01);
#endif
#ifdef SHADOW_FILTER_PCSS
shadow = pcss_spot(shadowCoord, last_spot_light, light.shadowsEnable.y);
#endif
last_spot_light++;
}
const float inner_cutoff = light.colorSize.w + radians(5);
const float outer_cutoff = light.colorSize.w;
const float theta = dot(light_info.direction, normalize(light.directionPower.xyz));
const float epsilon = inner_cutoff - outer_cutoff;
const float intensity = clamp((theta - outer_cutoff) / epsilon, 0.0, 1.0);
light_info.radiance = light.directionPower.w * shadow * intensity;
return light_info;
}
#ifdef POINT_SHADOWS_SUPPORTED
vec3 sampleOffsetDirections[20] = vec3[]
(
vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1),
vec3( 1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1),
vec3( 1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0),
vec3( 1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1),
vec3( 0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1)
);
float pcf_point(const vec3 shadowCoords, const int index, const float uvRadius) {
float sum = 0;
for(int i = 0; i < 20; i++) {
const float z = texture(point_shadow, vec4(shadowCoords.xyz + sampleOffsetDirections[i] * uvRadius, index)).r;
sum += (z < length(shadowCoords) - 0.05) ? 0.0 : 1.0;
}
return sum / 20;
}
#ifdef SHADOW_FILTER_PCSS
void blocker_distance_point(const vec3 shadowCoords, const int index, const float uvLightSize, inout float avgBlockerDistance, inout int blockers) {
const float searchWidth = search_width(uvLightSize, length(shadowCoords));
float blockerSum = 0.0;
blockers = 0;
for(int i = 0; i < 20; i++) {
const float z = texture(point_shadow, vec4(shadowCoords + sampleOffsetDirections[i] * 0.05, index)).r;
if(z < length(shadowCoords)) {
blockerSum += z;
blockers++;
}
}
avgBlockerDistance = blockerSum / blockers;
}
float pcss_point(const vec3 shadowCoords, const int index, float light_size_uv) {
float average_blocker_depth = 0.0;
int num_blockers = 0;
blocker_distance_point(shadowCoords.xyz, index, light_size_uv, average_blocker_depth, num_blockers);
if(num_blockers < 1)
return 1.0;
const float dist = length(shadowCoords);
const float penumbraWidth = penumbra_size(dist, average_blocker_depth);
const float uvRadius = penumbraWidth * light_size_uv / dist;
return pcf_point(shadowCoords, index, uvRadius);
}
#endif
#endif
ComputedLightInformation calculate_point(Light light) {
ComputedLightInformation light_info;
light_info.direction = normalize(light.positionType.xyz - in_frag_pos);
const vec3 lightVec = in_frag_pos - light.positionType.xyz;
// Check if fragment is in shadow
float shadow = 1.0;
#ifdef POINT_SHADOWS_SUPPORTED
if(light.shadowsEnable.x == 1.0) {
#ifdef SHADOW_FILTER_NONE
const float sampledDist = texture(point_shadow, vec4(lightVec, int(light.shadowsEnable.z))).r;
const float dist = length(lightVec);
shadow = (dist <= sampledDist + 0.05) ? 1.0 : 0.0;
#endif
#ifdef SHADOW_FILTER_PCF
shadow = pcf_point(lightVec, int(light.shadowsEnable.z), 0.05);
#endif
#ifdef SHADOW_FILTER_PCSS
shadow = pcss_point(lightVec, int(light.shadowsEnable.z), light.shadowsEnable.y);
#endif
}
#endif
const float distance = length(light.positionType.xyz - in_frag_pos);
const float attenuation = 1.0 / (distance * distance);
light_info.radiance = attenuation * light.directionPower.w * shadow;
return light_info;
}