MagicNStuff/source/addons/SunshineClouds2/SunshineCloudsCompute.glsl

955 lines
38 KiB
GLSL

#[compute]
#version 450
#define PI 3.141592
#define ABSORPTION_COEFFICIENT 0.9
#include "./CloudsInc.txt"
// Invocations in the (x, y, z) dimension
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
layout(rgba16f, binding = 0) uniform image2D output_data_image;
layout(rgba16f, binding = 1) uniform image2D output_color_image;
layout(rgba32f, binding = 2) uniform image2D accum_1A_image;
layout(rgba32f, binding = 3) uniform image2D accum_1B_image;
layout(rgba32f, binding = 4) uniform image2D accum_2A_image;
layout(rgba32f, binding = 5) uniform image2D accum_2B_image;
layout(binding = 6) uniform sampler2D depth_image;
layout(binding = 7) uniform sampler2D extra_large_noise;
layout(binding = 8) uniform sampler3D large_noise;
layout(binding = 9) uniform sampler3D noise_medium;
layout(binding = 10) uniform sampler3D noise_small;
layout(binding = 11) uniform sampler3D curl_noise;
layout(binding = 12) uniform sampler3D dither_small;
layout(binding = 13) uniform sampler2D heightmask;
layout(binding = 14) uniform uniformBuffer {
GenericData data;
} genericData;
layout(binding = 15) uniform LightsBuffer {
DirectionalLight directionalLights[4];
PointLight pointLights[128];
PointEffector pointEffectors[64];
};
layout(binding = 16, std430) restrict buffer SamplePointsBuffer {
vec4 SamplePoints[32];
};
layout(binding = 17, std140) uniform SceneDataBlock {
SceneData data;
SceneData prev_data;
} scene_data_block;
// Our push constant
// layout(push_constant, std430) uniform Params {
// vec2 raster_size;
// float large_noise_scale;
// float medium_noise_scale;
// float time;
// float cloud_coverage;
// float cloud_density;
// float small_noise_strength;
// float cloud_lighting_power;
// float accumilation_decay;
// vec2 cameraRotation;
// } params;
//Helpers
const int BayerFilter16[16] =
{
0, 8, 2, 10,
12, 4, 14, 6,
3, 11, 1, 9,
15, 7, 13, 5
};
const int BayerFilter4[4] =
{
0, 1,
3, 2,
};
const mat4 bayer_matrix = mat4(
vec4(00.0 / 16.0, 12.0 / 16.0, 03.0 / 16.0, 15.0 / 16.0),
vec4(08.0 / 16.0, 04.0 / 16.0, 11.0 / 16.0, 07.0 / 16.0),
vec4(02.0 / 16.0, 14.0 / 16.0, 01.0 / 16.0, 13.0 / 16.0),
vec4(10.0 / 16.0, 06.0 / 16.0, 09.0 / 16.0, 05.0 / 16.0));
float quadraticOut(float t) {
return -t * (t - 2.0);
}
float quadraticIn(float t) {
return t * t;
}
float rand(vec2 co){
return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453);
}
float get_dither_value(vec2 pixel) {
int x = int(pixel.x - 4.0 * floor(pixel.x / 4.0));
int y = int(pixel.y - 4.0 * floor(pixel.y / 4.0));
return bayer_matrix[x][y];
}
float remap(float value, float min1, float max1, float min2, float max2) {
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
}
float BeersLaw (float dist, float absorption) {
return exp(-dist * absorption);
}
float Powder (float dist, float absorption) {
return 1.0 - exp(-dist * absorption * 2.0);
}
float HenyeyGreenstein(float g, float costh)
{
return (1.0 - g * g) / (4.0 * PI * pow(1.0 + g * g - 2.0 * g * costh, 3.0/2.0));
}
bool renderBayer(ivec2 fragCoord, int framecount)
{
//int BAYER = 16;
//int index = framecount % BAYER;
return (fragCoord.x + 4 * fragCoord.y) % 16 == BayerFilter16[framecount];
}
//Sample functions
float sampleEffectorAdditive(vec3 worldPosition) {
float effectorAdditive = 0.0;
for (int i = 0; i < int(genericData.data.pointEffectorCount); i++) {
float effectorDistance = distance(pointEffectors[i].position, worldPosition);
if (effectorDistance < pointEffectors[i].radius){
effectorAdditive += mix(pointEffectors[i].power, 0.0, effectorDistance / pointEffectors[i].radius);
}
}
return effectorAdditive;
}
float sampleScene(
vec3 largeNoisePos,
vec3 mediumNoisePos,
vec3 smallNoisePos,
vec3 worldPosition,
float cloudceiling,
float cloudfloor,
float extralargeNoiseValue,
float largenoisescale,
float mediumnoisescale,
float smallnoisescale,
float coverage,
float smallscalePower,
float curlPower,
float lod,
bool ambientsample)
{
float clampedWorldHeight = remap(worldPosition.y, cloudfloor, cloudceiling, 0.0, 1.0);
vec4 gradientSample = texture(heightmask, vec2(clampedWorldHeight, 0.5)).rgba;
float edgeFade = min(smoothstep(0.0, 0.1, clampedWorldHeight), smoothstep(1.0, 0.9, clampedWorldHeight));
float extraLargeShape = extralargeNoiseValue * gradientSample.b;
float smallShape = texture(noise_small, (worldPosition - smallNoisePos) / smallnoisescale).r;
float curlHeightSample = (1.0 - gradientSample.a);
float effectorAdditive = 0.0;
vec2 WindDirection = genericData.data.WindDirection;
worldPosition += vec3(WindDirection.x, 0.0, WindDirection.y) * genericData.data.windSweptPower * quadraticIn(1.0 - clamp(clampedWorldHeight / genericData.data.windSweptRange, 0.0, 1.0));
if (lod > 0.0){
effectorAdditive = sampleEffectorAdditive(worldPosition) * edgeFade;
if (!ambientsample && curlHeightSample > 0.0 && min(curlPower, lod) > 0.5){
float curlLod = remap(lod, 0.5, 1.0, 0.0, 1.0);
worldPosition += (((texture(curl_noise, (worldPosition - mediumNoisePos) / mediumnoisescale).xyz * 2.0) - 1.0) * vec3(1.0, 0.2, 1.0) + vec3(WindDirection.x, 0.0, WindDirection.y) * 0.9) * curlPower * curlHeightSample * curlLod;
worldPosition += (((texture(curl_noise, (worldPosition - mediumNoisePos) / mediumnoisescale).xyz * 2.0) - 1.0) * vec3(1.0, 0.2, 1.0) + vec3(WindDirection.x, 0.0, WindDirection.y) * 0.9) * curlPower * curlHeightSample * curlLod;
worldPosition += (((texture(curl_noise, (worldPosition - mediumNoisePos) / mediumnoisescale).xyz * 2.0) - 1.0) * vec3(1.0, 0.2, 1.0) + vec3(WindDirection.x, 0.0, WindDirection.y) * 0.9) * curlPower * curlHeightSample * curlLod;
clampedWorldHeight = remap(worldPosition.y, cloudfloor, cloudceiling, 0.0, 1.0);
gradientSample = texture(heightmask, vec2(clampedWorldHeight, 0.5)).rgba;
}
}
float largeShape = texture(large_noise, (worldPosition - largeNoisePos) / largenoisescale).r * extraLargeShape;
largeShape = smoothstep(coverage , coverage - 0.1, 1.0 - (largeShape * gradientSample.r)) + max(effectorAdditive, 0.0);
vec4 mediumShapes = texture(noise_medium, (worldPosition - mediumNoisePos) / mediumnoisescale).rgba;
float mediumshape = 1.0 - mediumShapes.b;
smallShape = smallShape * gradientSample.g * pow((1.0 - mediumshape), smallscalePower);
float shape = mediumshape + max(effectorAdditive, 0.0);
shape = clamp(remap(shape, 1.0 - largeShape, 1.0, 0.0, 1.0), 0.0, 1.0);
shape = clamp(remap(shape, smallShape, 1.0, 0.0, 1.0), 0.0, 1.0);
shape += min(effectorAdditive, 0.0);
return clamp((shape * edgeFade), 0.0, 1.0);
}
float sampleSceneCoarse(
vec3 largeNoisePos,
vec3 worldPosition,
float cloudceiling,
float cloudfloor,
float extralargeNoiseValue,
float largenoisescale,
float coverage,
float lod)
{
float clampedWorldHeight = remap(worldPosition.y, cloudfloor, cloudceiling, 0.0, 1.0);
vec4 gradientSample = texture(heightmask, vec2(clampedWorldHeight, 0.5)).rgba;
float edgeFade = min(smoothstep(0.0, 0.1, clampedWorldHeight), smoothstep(1.0, 0.9, clampedWorldHeight));
float extraLargeShape = extralargeNoiseValue * gradientSample.b;
float effectorAdditive = 0.0;
vec2 WindDirection = genericData.data.WindDirection;
worldPosition += vec3(WindDirection.x, 0.0, WindDirection.y) * genericData.data.windSweptPower * quadraticIn(1.0 - clamp(clampedWorldHeight / genericData.data.windSweptRange, 0.0, 1.0));
if (lod > 0.0){
effectorAdditive = sampleEffectorAdditive(worldPosition) * edgeFade;
}
float largeShape = texture(large_noise, (worldPosition - largeNoisePos) / largenoisescale).r * extraLargeShape;
largeShape = smoothstep(coverage , coverage - 0.1, 1.0 - (largeShape * gradientSample.r)) + max(effectorAdditive, 0.0);
float shape = largeShape + effectorAdditive;
return clamp((shape * edgeFade), 0.0, 1.0);
}
float sampleLighting(
int stepCount,
vec3 worldPosition,
vec3 extralargeNoisePos,
vec3 largeNoisePos,
vec3 mediumNoisePos,
vec3 smallNoisePos,
vec3 sunDirection,
float densityMultiplier,
float sunUpWeight,
float stepDistance,
float cloudceiling,
float cloudfloor,
float extralargenoisescale,
float largenoisescale,
float mediumnoisescale,
float smallnoisescale,
float coverage,
float smallscalePower,
float curlPower,
float lod)
{
float density = 0.0;
float stepCountFloat = max(float(stepCount) * lod, 2.0);
float actualDistance = mix(stepDistance * 4.0, stepDistance, lod);
float eachShortStep = actualDistance / (float(stepCount) / stepCountFloat) / stepCountFloat;
float traveledDistance = 0.0;
float sunUpValue = 1.0 - sunUpWeight;
float eachStepWeight = 1.0 / stepCountFloat;
float heightGradient = 0.0;
float thisDensity = 0.0;
float count = 0.0;
vec3 curPos = worldPosition;
for (float i = 0.0; i < stepCountFloat; i++) {
traveledDistance = mix(eachShortStep, actualDistance, clamp(quadraticOut(i / stepCountFloat), 0.0, 1.0));
curPos = worldPosition + sunDirection * traveledDistance;
if (density < 1.0 && clamp(curPos.y, cloudfloor, cloudceiling) == curPos.y){
heightGradient = remap(curPos.y, cloudfloor, cloudceiling, 0.0, 1.0);
heightGradient = clamp(smoothstep(sunUpValue - 0.1, sunUpValue, heightGradient), 0.0, 1.0);
float extraLargeShape = texture(extra_large_noise, (curPos.xz - extralargeNoisePos.xz) / extralargenoisescale).a;
thisDensity = sampleScene(largeNoisePos, mediumNoisePos, smallNoisePos, curPos, cloudceiling, cloudfloor, extraLargeShape, largenoisescale, mediumnoisescale, smallnoisescale, coverage, smallscalePower, curlPower, lod, true) * densityMultiplier * eachStepWeight;
density += mix(1.0, thisDensity, heightGradient);
}
else{
break;
}
}
return density;
}
float sampleAO(
vec3 extralargeNoisePos,
vec3 largeNoisePos,
vec3 mediumNoisePos,
vec3 smallNoisePos,
vec3 worldPosition,
float lightingSampleRange,
float cloudceiling,
float cloudfloor,
float extralargenoisescale,
float largenoisescale,
float mediumnoisescale,
float smallnoisescale,
float coverage,
float smallscalePower,
float curlPower,
float lod)
{
vec3 samplePos = worldPosition;
samplePos.y += lightingSampleRange * 0.5;
samplePos.y += lightingSampleRange * (rand(samplePos.xz) * 2.0 - 1.0);
samplePos.x += lightingSampleRange * (rand(samplePos.zy) * 2.0 - 1.0);
samplePos.z += lightingSampleRange * (rand(samplePos.yx) * 2.0 - 1.0);
float extraLargeShape = texture(extra_large_noise, (samplePos.xz - extralargeNoisePos.xz) / extralargenoisescale).a;
return sampleScene(largeNoisePos, mediumNoisePos, smallNoisePos, samplePos, cloudceiling, cloudfloor, extraLargeShape, largenoisescale, mediumnoisescale, smallnoisescale, coverage, smallscalePower, curlPower, lod, true);
}
void sampleAtmospherics(
vec3 curPos,
float atmosphericHeight,
float distanceTraveled,
float Rayleighscaleheight,
float Miescaleheight,
vec3 RayleighScatteringCoef,
float MieScatteringCoef,
float atmosphericDensity,
float density,
inout vec3 totalRlh,
inout vec3 totalMie,
inout float iOdRlh,
inout float iOdMie)
{
float iHeight = curPos.y / atmosphericHeight;
float odStepRlh = exp(-iHeight / Rayleighscaleheight) * distanceTraveled;
float odStepMie = exp(-iHeight / Miescaleheight) * distanceTraveled;
iOdRlh += odStepRlh;
iOdMie += odStepMie;
vec3 attn = exp(-(MieScatteringCoef * (iOdMie + Miescaleheight) + RayleighScatteringCoef * (iOdRlh + Rayleighscaleheight))) * atmosphericDensity * (1.0 - clamp(iHeight, 0.0, 1.0));
totalRlh += odStepRlh * attn * (1.0 - density);
totalMie += odStepMie * attn * (1.0 - density);
}
vec4 sampleAllAtmospherics(
vec3 worldPos,
vec3 rayDirection,
float linear_depth,
float highestDensityDistance,
float density,
float stepDistance,
float stepCount,
float atmosphericDensity,
vec3 sunDirection,
vec3 sunlightColor,
vec3 ambientLight)
{
vec3 totalRlh = vec3(0,0,0);
vec3 totalMie = vec3(0,0,0);
float iOdRlh = 0.0;
float iOdMie = 0.0;
// float odStepRlh = 0.0;
// float odStepMie = 0.0;
const float atmosphericHeight = 40000.0;
const vec3 RayleighScatteringCoef = vec3(5.5e-6, 13.0e-6, 22.4e-6);
const float Rayleighscaleheight = 8e3;
const float MieScatteringCoef = 21e-6;
const float Miescaleheight = 1.2e3;
const float MieprefferedDirection = 0.758;
// Calculate the Rayleigh and Mie phases.
float mu = dot(rayDirection, sunDirection);
float mumu = mu * mu;
float gg = MieprefferedDirection * MieprefferedDirection;
float pRlh = 3.0 / (16.0 * PI) * (1.0 + mumu);
float pMie = 3.0 / (8.0 * PI) * ((1.0 - gg) * (mumu + 1.0)) / (pow(1.0 + gg - 2.0 * mu * MieprefferedDirection, 1.5) * (2.0 + gg));
vec3 curPos = vec3(0.0);
float traveledDistance = 0.0;
//bool sampledDistanceAtmo = false;
float currentWeight = 0.0;
float sampleCount = 0.0;
for (float i = 0.0; i < stepCount; i++) {
traveledDistance = stepDistance * (i + 1);
currentWeight = density * (1.0 - clamp((highestDensityDistance - traveledDistance) / stepDistance, 0.0, 1.0));
if (traveledDistance > linear_depth || currentWeight >= 1.0){
traveledDistance = traveledDistance - stepDistance;
currentWeight = 1.0 - clamp((linear_depth - traveledDistance) / stepDistance, 0.0, 1.0);
sampleAtmospherics(curPos, atmosphericHeight, stepDistance, Rayleighscaleheight, Miescaleheight, RayleighScatteringCoef, MieScatteringCoef, atmosphericDensity, currentWeight, totalRlh, totalMie, iOdRlh, iOdMie);
break;
}
sampleCount += 1.0;
curPos = worldPos + rayDirection * traveledDistance;
sampleAtmospherics(curPos, atmosphericHeight, stepDistance, Rayleighscaleheight, Miescaleheight, RayleighScatteringCoef, MieScatteringCoef, atmosphericDensity, currentWeight, totalRlh, totalMie, iOdRlh, iOdMie);
}
// pRlh *= (1.0 - lightingWeight);
// pMie *= (1.0 - lightingWeight);
float AtmosphericsDistancePower = length(vec3(RayleighScatteringCoef * totalRlh + MieScatteringCoef * totalMie));
vec3 atmospherics = 22.0 * (ambientLight * RayleighScatteringCoef * totalRlh + pMie * MieScatteringCoef * sunlightColor * totalMie) / sampleCount;
return vec4(atmospherics, AtmosphericsDistancePower);
}
void main() {
//SETTING UP UVS/RAY DATA
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = ivec2(genericData.data.raster_size);
// Prevent reading/writing out of bounds.
if (uv.x >= size.x || uv.y >= size.y) {
return;
}
vec2 depthUV = vec2(float(uv.x) / float(size.x), float(uv.y) / float(size.y));
float depth = texture(depth_image, depthUV).r;
vec4 view = inverse(scene_data_block.data.projection_matrix) * vec4(depthUV*2.0-1.0,depth,1.0);
view.xyz /= view.w;
float linear_depth = length(view); //used to calculate depth based on the view angle, idk just works.
//4.4 doesn't work with this
// if (linear_depth > scene_data_block.data.z_far){
// linear_depth *= 100.0;
// }
// Convert screen coordinates to normalized device coordinates
vec2 clipUV = vec2(depthUV.x, depthUV.y);
vec2 ndc = clipUV * 2.0 - 1.0;
// Convert NDC to view space coordinates
vec4 clipPos = vec4(ndc, 0.0, 1.0);
vec4 viewPos = inverse(scene_data_block.data.projection_matrix) * clipPos;
viewPos.xyz /= viewPos.w;
vec3 rd_world = normalize(viewPos.xyz);
rd_world = mat3(scene_data_block.data.main_cam_inv_view_matrix) * rd_world;
// Define the ray properties
vec3 raydirection = normalize(rd_world);
vec3 rayOrigin = scene_data_block.data.main_cam_inv_view_matrix[3].xyz; //center of camera for the ray origin, not worried about the screen width playing in, as it's for clouds.
//DITHER
float ditherScale = 40.037;
vec3 ditherUV = vec3(depthUV.x * ditherScale , depthUV.y * ditherScale , genericData.data.time);
float smallNoise = texture(dither_small, ditherUV).r;
float ditherValue = smallNoise;
//ATMOSPHERICS
vec3 ambientfogdistancecolor = genericData.data.ambientfogdistancecolor.rgb;
vec3 totalRlh = vec3(0,0,0);
vec3 totalMie = vec3(0,0,0);
float iOdRlh = 0.0;
float iOdMie = 0.0;
float atmosphericDensity = genericData.data.atmospheric_density;
const float atmosphericHeight = 40000.0;
const vec3 RayleighScatteringCoef = vec3(5.5e-6, 13.0e-6, 22.4e-6);
const float Rayleighscaleheight = 8e3;
const float MieScatteringCoef = 21e-6;
const float Miescaleheight = 1.2e3;
const float MieprefferedDirection = 0.758;
//IMPORTED DATA
int stepCount = int(genericData.data.max_step_count);
int lightingStepCount = int(genericData.data.max_lighting_step_count);
int directionalLightCount = int(genericData.data.directionalLightsCount);
int pointLightCount = int(genericData.data.pointLightsCount);
vec3 extralargeNoisePos = genericData.data.extralargenoiseposition;
vec3 largeNoisePos = genericData.data.largenoiseposition;
vec3 mediumNoisePos = genericData.data.mediumnoiseposition;
vec3 smallNoisePos = genericData.data.smallnoiseposition;
float extralargenoiseScale = genericData.data.extralargenoisescale;
float largenoiseScale = genericData.data.large_noise_scale;
float mediumnoiseScale = genericData.data.medium_noise_scale;
float smallnoiseScale = genericData.data.small_noise_scale;
float minstep = genericData.data.min_step_distance;
float maxstep = genericData.data.max_step_distance;
float curlPower = genericData.data.curlPower;
float lightingStepDistance = genericData.data.lighting_step_distance;
float cloudfloor = genericData.data.cloud_floor;
float cloudceiling = genericData.data.cloud_ceiling;
float densityMultiplier = genericData.data.cloud_density;
float sharpness = clamp(1.0 - genericData.data.cloud_sharpness, 0.001, 1.0) * 2.0;
float lightingSharpness = genericData.data.cloud_lighting_sharpness;
float smallNoiseMultiplier = genericData.data.small_noise_strength;
float coverage = genericData.data.cloud_coverage * 1.01;
float lightingdensityMultiplier = genericData.data.cloud_lighting_power;
lightingdensityMultiplier += lightingdensityMultiplier * 3.0 * coverage;
vec4 aobase = genericData.data.ambientGroundLightColor;
//bool debugCollisions = false;
//int frameIndex = int(genericData.data.filterIndex);
//REUSABLE VARIABLES
bool override = false;
bool densityBreak = false;
bool depthBreak = false;
float maxTheoreticalStep = float(stepCount) * maxstep;
float highestDensity = 0.0;
float highestDensityDistance = maxTheoreticalStep;
float ceilingSample = cloudceiling;
float lodMaxDistance = maxstep * float(stepCount) * genericData.data.lod_bias;
float halfcloudThickness = (cloudceiling - cloudfloor) * 0.5;
float halfCeiling = cloudceiling - halfcloudThickness;
float newStep = maxstep * ditherValue;
float traveledDistance = newStep;
vec4 currentColorAccumilation = vec4(0.0);
vec4 currentDataAccumilation = vec4(0.0);
//Used for interlaced rendering, not currently enabled due to it's long accumilation time, results in a lot of noticable artifacts.
//Though it does improve performance, so maybe for some people it will be helpful.
//bool rebuildFrame = renderBayer(uv, frameIndex);
// bool rebuildFrame = true;
// if (!rebuildFrame){
// //accumulation preperation:
// vec4 niaveDataRetreval = vec4(0.0);
// float usingaccumA = genericData.data.isAccumulationA;
// if (usingaccumA > 0.0){
// niaveDataRetreval = imageLoad(accum_2A_image, uv).rgba;
// }
// else{
// niaveDataRetreval = imageLoad(accum_2B_image, uv).rgba;
// }
// //depthBreak = niaveDataRetreval.r > linear_depth;
// vec3 worldFinalPos = curPos + raydirection * niaveDataRetreval.g;
// worldFinalPos += (rayOrigin - genericData.data.prevview[3].xyz);
// //Prevview is already actually the inv_view (due to the way retrieving the transform works), so inversing it here is making it the equalivant of View_Matrix.
// vec4 reprojectedClipPos = inverse(genericData.data.prevview) * vec4(worldFinalPos, 1.0);
// if (reprojectedClipPos.z > 0.0){
// override = true;
// }
// else{
// vec4 reprojectedScreenPos = genericData.data.prevproj * reprojectedClipPos;
// // Convert clip space to normalized device coordinates
// ndc = (reprojectedScreenPos.xy / reprojectedScreenPos.w);
// // Convert normalized device coordinates to screen space
// vec2 screen_position = ndc * 0.5 + 0.5;
// //screen_position = clamp(screen_position, vec2(0.0), vec2(1.0));
// screen_position = screen_position - depthUV;
// ivec2 adjustedUV = ivec2(int(screen_position.x * size.x), int(screen_position.y * size.y));
// //float change = length(vec2(adjustedUV));
// adjustedUV += uv; //Size is the screen resolution.
// ivec2 clampedUV = clamp(adjustedUV, ivec2(0), size - ivec2(1)); //having two lets me check if clamping it changed the reprojected uv, if it did that means it was offscreen, so rebuild data.
// //execute accumilation.
// float accumdecay = genericData.data.accumilation_decay;
// //alternate back and forth to avoid stepping on pixels being written too.
// float actualDepth = abs(reprojectedClipPos.z);
// if (usingaccumA > 0.0){
// currentDataAccumilation = imageLoad(accum_2A_image, adjustedUV).rgba;
// bool lastDepthBreak = currentDataAccumilation.a < 0.0;
// float sampledDepth = currentDataAccumilation.r;
// depthBreak = actualDepth > sampledDepth;
// if (clampedUV != adjustedUV || depthBreak != lastDepthBreak){
// override = true;
// //debugCollisions = true;
// }
// else{
// imageStore(accum_1B_image, uv, imageLoad(accum_1A_image, adjustedUV));
// imageStore(accum_2B_image, uv, currentDataAccumilation);
// }
// }
// else{
// currentDataAccumilation = imageLoad(accum_2B_image, adjustedUV).rgba;
// bool lastDepthBreak = currentDataAccumilation.a < 0.0;
// float sampledDepth = abs(currentDataAccumilation.r);
// depthBreak = actualDepth > sampledDepth;
// if (clampedUV != adjustedUV || depthBreak != lastDepthBreak){
// override = true;
// //debugCollisions = true;
// }
// else{
// imageStore(accum_1A_image, uv, imageLoad(accum_1B_image, adjustedUV));
// imageStore(accum_2A_image, uv, currentDataAccumilation);
// }
// }
// }
// }
// END INTERLACED RENDERING
//if (rebuildFrame || override){ //Re-enable for interlaced rendering
//If it is our render, build the data for this pixel
vec3 directionalLightSunUpPower[4] = vec3[4](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
float totalLightPower = 0.0;
for (int lightI = 0; lightI < directionalLightCount; lightI++){
if (directionalLights[lightI].color.a > 0.0){
directionalLightSunUpPower[lightI].r = smoothstep(-0.03, 0.07, dot(directionalLights[lightI].direction.xyz, vec3(0.0, 1.0, 0.0)));
totalLightPower += directionalLights[lightI].color.a * directionalLightSunUpPower[lightI].r;
directionalLightSunUpPower[lightI].b = dot(directionalLights[lightI].direction.xyz, raydirection);
}
}
vec4 lightColor = vec4(0.0);
vec3 paintedColor = vec3(0.0);
float initialdistanceSample = -1.0;
float lightingSamples = 0.0;
float atmoSamples = 0.0;
float density = 0.0;
float ambient = 0.0;
float depthFade = 1.0;
float newdensity = 0.0;
vec3 curPos = vec3(0.0);
float curLod = 1.0;
float samplePosCount = genericData.data.samplePointsCount;
if (samplePosCount > 0 && uv == ivec2(0)){
for (int i = 0; i < samplePosCount; i++){
curPos = SamplePoints[i].xyz;
vec4 maskSample = texture(extra_large_noise, (curPos.xz - extralargeNoisePos.xz) / extralargenoiseScale);
ceilingSample = mix(halfCeiling, cloudceiling, maskSample.a);
SamplePoints[i].w = pow(sampleScene(largeNoisePos, mediumNoisePos, smallNoisePos, curPos, ceilingSample, cloudfloor, maskSample.a, largenoiseScale, mediumnoiseScale, smallnoiseScale, coverage, smallNoiseMultiplier, curlPower, 1.0, false) * densityMultiplier, sharpness);
}
}
for (int i = 0; i < stepCount; i++) {
if (traveledDistance > linear_depth){
depthFade = 1.0 - smoothstep(linear_depth - newStep, linear_depth, traveledDistance);
depthBreak = true;
}
curPos = rayOrigin + raydirection * traveledDistance;
vec4 maskSample = texture(extra_large_noise, (curPos.xz - extralargeNoisePos.xz) / extralargenoiseScale);
ceilingSample = mix(halfCeiling, cloudceiling, maskSample.a);
//sampleAtmospherics(curPos, atmosphericHeight, newStep, Rayleighscaleheight, Miescaleheight, RayleighScatteringCoef, MieScatteringCoef, atmosphericDensity, density, totalRlh, totalMie, iOdRlh, iOdMie);
atmoSamples += 1.0;
if (clamp(curPos.y, cloudfloor, cloudceiling) == curPos.y){
curLod = 1.0 - clamp(traveledDistance / lodMaxDistance, 0.0, 1.0);
newdensity = sampleSceneCoarse(largeNoisePos, curPos, ceilingSample, cloudfloor, maskSample.a, largenoiseScale, coverage, curLod);
if (newdensity > 0.0) {
newdensity = pow(sampleScene(largeNoisePos, mediumNoisePos, smallNoisePos, curPos, ceilingSample, cloudfloor, maskSample.a, largenoiseScale, mediumnoiseScale, smallnoiseScale, coverage, smallNoiseMultiplier, curlPower, curLod, false) * densityMultiplier, sharpness) * depthFade;
}
if (newdensity > 0.0){
if (initialdistanceSample < 0.0){
initialdistanceSample = traveledDistance;
}
float powderEffect = pow(newdensity, genericData.data.powderStrength * 2.0);
paintedColor += maskSample.rgb;
lightingSamples += 1.0;
for (int lightI = 0; lightI < directionalLightCount; lightI++){
vec3 sundir = directionalLights[lightI].direction.xyz;
float sunUpWeight = directionalLightSunUpPower[lightI].r;
int thislightingStepCount = min(int(directionalLights[lightI].direction.w), lightingStepCount);
float henyeygreenstein = pow(HenyeyGreenstein(genericData.data.anisotropy, directionalLightSunUpPower[lightI].b), mix(1.0, 2.0, 1.0 - genericData.data.anisotropy));
float densitySample = sampleLighting(thislightingStepCount, curPos, extralargeNoisePos, largeNoisePos, mediumNoisePos, smallNoisePos, sundir, densityMultiplier * lightingdensityMultiplier, sunUpWeight, lightingStepDistance, ceilingSample, cloudfloor, extralargenoiseScale, largenoiseScale, mediumnoiseScale, smallnoiseScale, coverage, smallNoiseMultiplier, curlPower, curLod);
densitySample = BeersLaw(lightingStepDistance, densitySample * henyeygreenstein);
//densitySample = Powder(lightingStepDistance, densitySample);
float thisStepLightingWeight = (clamp(pow(densitySample, lightingSharpness), 0.0, 1.0)) * sunUpWeight;
lightColor.rgb += pow(directionalLights[lightI].color.rgb * directionalLights[lightI].color.a * thisStepLightingWeight, vec3(2.2)) * powderEffect;
directionalLightSunUpPower[lightI].g += directionalLights[lightI].color.a * thisStepLightingWeight;
// if (thislightingStepCount > 0){
// float henyeygreenstein = pow(HenyeyGreenstein(genericData.data.anisotropy, directionalLightSunUpPower[lightI].b), mix(1.0, 2.0, 1.0 - genericData.data.anisotropy));
// float densitySample = sampleLighting(thislightingStepCount, curPos, extralargeNoisePos, largeNoisePos, mediumNoisePos, smallNoisePos, sundir, densityMultiplier * lightingdensityMultiplier, sunUpWeight, lightingStepDistance, ceilingSample, cloudfloor, extralargenoiseScale, largenoiseScale, mediumnoiseScale, smallnoiseScale, coverage, smallNoiseMultiplier, curlPower, curLod);
// densitySample = BeersLaw(lightingStepDistance, densitySample * henyeygreenstein);
// //densitySample = Powder(lightingStepDistance, densitySample);
// float thisStepLightingWeight = (clamp(pow(densitySample, lightingSharpness), 0.0, 1.0)) * sunUpWeight;
// lightColor.rgb += pow(directionalLights[lightI].color.rgb * directionalLights[lightI].color.a * thisStepLightingWeight, vec3(2.2)) * powderEffect;
// directionalLightSunUpPower[lightI].g += directionalLights[lightI].color.a * thisStepLightingWeight;
// }
// else{
// lightColor.rgb += pow(directionalLights[lightI].color.rgb * directionalLights[lightI].color.a * sunUpWeight, vec3(2.2)) * powderEffect;
// directionalLightSunUpPower[lightI].g += directionalLights[lightI].color.a * sunUpWeight;
// }
// if (directionalLights[lightI].color.a > 0.0){
// vec3 sundir = directionalLights[lightI].direction.xyz;
// float sunUpWeight = directionalLightSunUpPower[lightI].r;
// int thislightingStepCount = min(int(directionalLights[lightI].direction.w), lightingStepCount);
// if (thislightingStepCount > 0){
// float henyeygreenstein = pow(HenyeyGreenstein(genericData.data.anisotropy, directionalLightSunUpPower[lightI].b), mix(1.0, 2.0, 1.0 - genericData.data.anisotropy));
// float densitySample = sampleLighting(thislightingStepCount, curPos, extralargeNoisePos, largeNoisePos, mediumNoisePos, smallNoisePos, sundir, densityMultiplier * lightingdensityMultiplier, sunUpWeight, lightingStepDistance, ceilingSample, cloudfloor, extralargenoiseScale, largenoiseScale, mediumnoiseScale, smallnoiseScale, coverage, smallNoiseMultiplier, curlPower, curLod);
// densitySample = BeersLaw(lightingStepDistance, densitySample * henyeygreenstein);
// //densitySample = Powder(lightingStepDistance, densitySample);
// float thisStepLightingWeight = (clamp(pow(densitySample, lightingSharpness), 0.0, 1.0)) * sunUpWeight;
// lightColor.rgb += pow(directionalLights[lightI].color.rgb * directionalLights[lightI].color.a * thisStepLightingWeight, vec3(2.2)) * powderEffect;
// directionalLightSunUpPower[lightI].g += directionalLights[lightI].color.a * thisStepLightingWeight;
// }
// else{
// lightColor.rgb += pow(directionalLights[lightI].color.rgb * directionalLights[lightI].color.a * sunUpWeight, vec3(2.2)) * powderEffect;
// directionalLightSunUpPower[lightI].g += directionalLights[lightI].color.a * sunUpWeight;
// }
// }
}
for (int lightI = 0; lightI < pointLightCount; lightI++){
vec3 lightToOriginDelta = pointLights[lightI].position.xyz - curPos;
float lightDistanceWeight = length(lightToOriginDelta);
if (pointLights[lightI].color.a > 0.0 && lightDistanceWeight < pointLights[lightI].position.w){
lightToOriginDelta = normalize(lightToOriginDelta);
//float densitySample = 1.0 - newdensity;
float densitySample = sampleLighting(3, curPos, extralargeNoisePos, largeNoisePos, mediumNoisePos, smallNoisePos, lightToOriginDelta, densityMultiplier, 1.0, min(maxstep, lightDistanceWeight), ceilingSample, cloudfloor, extralargenoiseScale, largenoiseScale, mediumnoiseScale, smallnoiseScale, coverage, smallNoiseMultiplier, curlPower, curLod);
float henyeygreenstein = pow(HenyeyGreenstein(genericData.data.anisotropy, dot(lightToOriginDelta, raydirection)), mix(1.0, 2.0, 1.0 - genericData.data.anisotropy));
densitySample = BeersLaw(lightDistanceWeight, densitySample * henyeygreenstein);
densitySample = mix(densitySample, newdensity, 0.5) * powderEffect;
lightDistanceWeight = lightDistanceWeight / pointLights[lightI].position.w;
lightDistanceWeight = pointLights[lightI].color.a * pow((1.0 - lightDistanceWeight), 2.2) * densitySample;
lightColor.rgb += pow(pointLights[lightI].color.rgb * lightDistanceWeight, vec3(2.2));
}
}
if (aobase.a > 0.0){
ambient += sampleScene(largeNoisePos, mediumNoisePos, smallNoisePos, curPos + vec3(0.0, 1.0, 0.0) * minstep, ceilingSample, cloudfloor, maskSample.a, largenoiseScale, mediumnoiseScale, smallnoiseScale, coverage, smallNoiseMultiplier, curlPower, curLod, true) * densityMultiplier * lightingdensityMultiplier ;
}
newStep = mix(mix(maxstep, minstep, pow(newdensity, 0.1)), maxstep, float(i) / float(stepCount));
if (newdensity > highestDensity){
highestDensity = newdensity;
highestDensityDistance = traveledDistance;
}
}
else{
newStep = maxstep;
}
if (i == 0){
newdensity = mix(newdensity, 0.0, clamp(traveledDistance / maxstep, 0.0, 1.0));
}
density += newdensity;
if (density >= 1.0){
densityBreak = true;
break;
}
}
else{
if (min(curPos.y - cloudceiling, raydirection.y) > 0.0 || max(curPos.y - cloudfloor, raydirection.y) < 0.0){
traveledDistance = min(maxTheoreticalStep, linear_depth);
curPos = rayOrigin + raydirection * traveledDistance;
//debugCollisions = true;
break;
}
newStep = maxstep;
}
if (depthBreak){
break;
}
traveledDistance += newStep;
}
ambient = clamp(ambient / lightingSamples, 0.0, 1.0);
paintedColor = clamp(paintedColor / lightingSamples, 0.0, 1.0);
vec3 ambientLight = genericData.data.ambientLightColor.rgb * clamp(totalLightPower, 0.0, 1.0);
ambientLight = mix(ambientLight, ambientLight * aobase.rgb, clamp(ambient * aobase.a, 0.0, 1.0)) * paintedColor;
lightColor.rgb = ambientLight + clamp(lightColor.rgb / lightingSamples, vec3(0.0), vec3(2.0));
lightColor.a = density;
if (linear_depth > maxstep && directionalLightCount > 0.0){
for (float i = 0.0; i < directionalLightCount; i++){
DirectionalLight light = directionalLights[int(i)];
vec3 sundir = light.direction.xyz;
//sampleColor = sundir;
float sunUpWeight = smoothstep(0.0, 0.4, dot(sundir, vec3(0.0, 1.0, 0.0)));
float sundensityaffect = 1.0 - clamp(dot(sundir, raydirection) * density, 0.0, 1.0);
// sundensityaffect = min(1.0 - (sundensityaffect * density), 1.0 - (sundensityaffect * clamp(maxTheoreticalStep - linear_depth, 0.0, 1.0)));
float lightPower = light.color.a * sunUpWeight * sundensityaffect;
vec4 atmosphericData = sampleAllAtmospherics(rayOrigin, raydirection, linear_depth, traveledDistance, 0.0, traveledDistance / 10.0, 10.0, atmosphericDensity, sundir, light.color.rgb * lightPower, ambientfogdistancecolor);
lightColor.rgb = mix(lightColor.rgb, atmosphericData.rgb, clamp(atmosphericData.a, 0.0, 1.0)); //causes jitter in the sky
}
}
initialdistanceSample = max(initialdistanceSample, 0.0);
//accumulation preperation:
float finalDensityDistance = min(traveledDistance, highestDensityDistance);
vec3 worldFinalPos = rayOrigin + raydirection * traveledDistance;
vec3 delta = rayOrigin - scene_data_block.prev_data.main_cam_inv_view_matrix[3].xyz;
worldFinalPos += delta;
//Prevview is already actually the inv_view (due to the way retrieving the transform works), so inversing it here is making it the equalivant of View_Matrix.
vec4 reprojectedClipPos = scene_data_block.prev_data.view_matrix * vec4(worldFinalPos, 1.0);
reprojectedClipPos.z -= 0.01;
if (reprojectedClipPos.z > 0.0){
override = true;
}
vec4 reprojectedScreenPos = scene_data_block.prev_data.projection_matrix * reprojectedClipPos;
// Convert clip space to normalized device coordinates
ndc = (reprojectedScreenPos.xy / reprojectedScreenPos.w);
// Convert normalized device coordinates to screen space
vec2 screen_position = ndc * 0.5 + 0.5;
//screen_position = clamp(screen_position, vec2(0.0), vec2(1.0));
screen_position = screen_position - depthUV;
ivec2 adjustedUV = ivec2(int(screen_position.x * size.x), int(screen_position.y * size.y));
//float change = length(vec2(adjustedUV));
adjustedUV += uv; //Size is the screen resolution.
ivec2 clampedUV = clamp(adjustedUV, ivec2(0), size - ivec2(1)); //having two lets me check if clamping it changed the reprojected uv, if it did that means it was offscreen, so rebuild data.
//execute accumilation.
float accumdecay = genericData.data.accumilation_decay;
//alternate back and forth to avoid stepping on pixels being written too.
float usingaccumA = genericData.data.isAccumulationA;
//float finalDensityDistance = max(traveledDistance, highestDensityDistance);
//linear_depth = max(linear_depth, traveledDistance);
float travelspeed = length(delta) + maxstep;
//bool debugCollisions = false;
if (usingaccumA > 0.0){
currentColorAccumilation = imageLoad(accum_1A_image, adjustedUV).rgba;
currentDataAccumilation = imageLoad(accum_2A_image, adjustedUV).rgba;
bool lastDepthBreak = currentDataAccumilation.a < 0.0;
if (override || clampedUV != adjustedUV || (depthBreak != lastDepthBreak && abs(linear_depth - currentDataAccumilation.r) > travelspeed)){
currentColorAccumilation = lightColor;
//debugCollisions = true;
currentDataAccumilation.r = linear_depth;
currentDataAccumilation.g = finalDensityDistance;
currentDataAccumilation.b = initialdistanceSample;
}
else{
currentColorAccumilation = (currentColorAccumilation * accumdecay) + lightColor * (1.0 - accumdecay);
currentDataAccumilation.r = mix(currentDataAccumilation.r, linear_depth, (1.0 - accumdecay));
currentDataAccumilation.g = mix(currentDataAccumilation.g, finalDensityDistance, (1.0 - accumdecay));
currentDataAccumilation.b = mix(currentDataAccumilation.b, initialdistanceSample, (1.0 - accumdecay));
}
if (depthBreak){
currentDataAccumilation.a = -1.0;
}
else{
currentDataAccumilation.a = 1.0;
}
imageStore(accum_1B_image, uv, currentColorAccumilation);
imageStore(accum_2B_image, uv, currentDataAccumilation);
}
else{
currentColorAccumilation = imageLoad(accum_1B_image, adjustedUV).rgba;
currentDataAccumilation = imageLoad(accum_2B_image, adjustedUV).rgba;
bool lastDepthBreak = currentDataAccumilation.a < 0.0;
if (override || clampedUV != adjustedUV || (depthBreak != lastDepthBreak && abs(linear_depth - currentDataAccumilation.r) > travelspeed)){
currentColorAccumilation = lightColor;
//debugCollisions = true;
currentDataAccumilation.r = linear_depth;
currentDataAccumilation.g = finalDensityDistance;
currentDataAccumilation.b = initialdistanceSample;
}
else{
currentColorAccumilation = (currentColorAccumilation * accumdecay) + lightColor * (1.0 - accumdecay);
currentDataAccumilation.r = mix(currentDataAccumilation.r, linear_depth, (1.0 - accumdecay));
currentDataAccumilation.g = mix(currentDataAccumilation.g, finalDensityDistance, (1.0 - accumdecay));
currentDataAccumilation.b = mix(currentDataAccumilation.b, initialdistanceSample, (1.0 - accumdecay));
}
if (depthBreak){
currentDataAccumilation.a = -1.0;
}
else{
currentDataAccumilation.a = 1.0;
}
imageStore(accum_1A_image, uv, currentColorAccumilation);
imageStore(accum_2A_image, uv, currentDataAccumilation);
}
currentDataAccumilation.a = abs(currentDataAccumilation.a);
imageStore(output_color_image, uv, currentColorAccumilation);
imageStore(output_data_image, uv, currentDataAccumilation);
//}
}