add fog
This commit is contained in:
+8
-6
@@ -29,6 +29,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
|||||||
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
||||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||||
import com.seibel.distanthorizons.core.util.objects.SortedArraySet;
|
import com.seibel.distanthorizons.core.util.objects.SortedArraySet;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
@@ -148,6 +149,7 @@ public class McLodRenderer
|
|||||||
|
|
||||||
IMcLodRenderer lodRenderer = SingletonInjector.INSTANCE.get(IMcLodRenderer.class);
|
IMcLodRenderer lodRenderer = SingletonInjector.INSTANCE.get(IMcLodRenderer.class);
|
||||||
IMcSsaoRenderer ssaoRenderer = SingletonInjector.INSTANCE.get(IMcSsaoRenderer.class);
|
IMcSsaoRenderer ssaoRenderer = SingletonInjector.INSTANCE.get(IMcSsaoRenderer.class);
|
||||||
|
IMcFogRenderer fogRenderer = SingletonInjector.INSTANCE.get(IMcFogRenderer.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -214,12 +216,12 @@ public class McLodRenderer
|
|||||||
// this is done to fix issues with: underwater fog, blindness effect, etc.
|
// this is done to fix issues with: underwater fog, blindness effect, etc.
|
||||||
|| renderParams.vanillaFogEnabled)
|
|| renderParams.vanillaFogEnabled)
|
||||||
{
|
{
|
||||||
//profiler.popPush("LOD Fog");
|
profiler.popPush("LOD Fog");
|
||||||
//
|
|
||||||
//Mat4f combinedMatrix = new Mat4f(renderParams.dhProjectionMatrix);
|
Mat4f combinedMatrix = new Mat4f(renderParams.dhProjectionMatrix);
|
||||||
//combinedMatrix.multiply(renderParams.dhModelViewMatrix);
|
combinedMatrix.multiply(renderParams.dhModelViewMatrix);
|
||||||
//
|
|
||||||
//FogRenderer.INSTANCE.render(combinedMatrix, renderParams.partialTicks);
|
fogRenderer.render(combinedMatrix, renderParams.partialTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -243,9 +243,9 @@ public class FogShader extends AbstractShaderRenderer
|
|||||||
return fogColor;
|
return fogColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProjectionMatrix(Mat4f projectionMatrix)
|
public void setProjectionMatrix(Mat4f modelViewProjectionMatrix)
|
||||||
{
|
{
|
||||||
this.inverseMvmProjMatrix = new Mat4f(projectionMatrix);
|
this.inverseMvmProjMatrix = new Mat4f(modelViewProjectionMatrix);
|
||||||
this.inverseMvmProjMatrix.invert();
|
this.inverseMvmProjMatrix.invert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.core.wrapperInterfaces.render;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||||
|
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||||
|
|
||||||
|
public interface IMcFogRenderer extends IBindable
|
||||||
|
{
|
||||||
|
|
||||||
|
void render(DhApiMat4f modelViewProjectionMatrix, float partialTicks);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#version 150 core
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
uniform sampler2D uColorTexture;
|
||||||
|
uniform sampler2D uDhDepthTexture;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fog application shader
|
||||||
|
*
|
||||||
|
* This merges the rendered fog onto DH's rendered LODs
|
||||||
|
*/
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
fragColor = vec4(0.0);
|
||||||
|
|
||||||
|
// a fragment depth of "1" means the fragment wasn't drawn to,
|
||||||
|
// only update fragments that were drawn to
|
||||||
|
float fragmentDepth = textureLod(uDhDepthTexture, TexCoord, 0).r;
|
||||||
|
if (fragmentDepth != 1)
|
||||||
|
{
|
||||||
|
fragColor = texture(uColorTexture, TexCoord);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,299 @@
|
|||||||
|
#version 150 core
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
layout (std140) uniform fragUniformBlock
|
||||||
|
{
|
||||||
|
// fog uniforms
|
||||||
|
vec4 uFogColor;
|
||||||
|
float uFogScale;
|
||||||
|
float uFogVerticalScale;
|
||||||
|
int uFogDebugMode;
|
||||||
|
int uFogFalloffType;
|
||||||
|
|
||||||
|
// fog config
|
||||||
|
float uFarFogStart;
|
||||||
|
float uFarFogLength;
|
||||||
|
float uFarFogMin;
|
||||||
|
float uFarFogRange;
|
||||||
|
float uFarFogDensity;
|
||||||
|
|
||||||
|
// height fog config
|
||||||
|
float uHeightFogStart;
|
||||||
|
float uHeightFogLength;
|
||||||
|
float uHeightFogMin;
|
||||||
|
float uHeightFogRange;
|
||||||
|
float uHeightFogDensity;
|
||||||
|
|
||||||
|
// ???
|
||||||
|
bool uHeightFogEnabled;
|
||||||
|
int uHeightFogFalloffType;
|
||||||
|
bool uHeightBasedOnCamera;
|
||||||
|
float uHeightFogBaseHeight;
|
||||||
|
bool uHeightFogAppliesUp;
|
||||||
|
bool uHeightFogAppliesDown;
|
||||||
|
bool uUseSphericalFog;
|
||||||
|
int uHeightFogMixingMode;
|
||||||
|
float uCameraBlockYPos;
|
||||||
|
|
||||||
|
// inverted model view matrix and projection matrix
|
||||||
|
mat4 uInvMvmProj;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform sampler2D uDhDepthTexture;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//====================//
|
||||||
|
// method definitions //
|
||||||
|
//====================//
|
||||||
|
|
||||||
|
vec3 calcViewPosition(float fragmentDepth);
|
||||||
|
|
||||||
|
float getFarFogThickness(float dist);
|
||||||
|
float getHeightFogThickness(float dist);
|
||||||
|
float calculateHeightFogDepth(float worldYPos);
|
||||||
|
float mixFogThickness(float far, float height);
|
||||||
|
|
||||||
|
float linearFog(float worldDist, float fogStart, float fogLength, float fogMin, float fogRange);
|
||||||
|
float exponentialFog(float x, float fogStart, float fogLength, float fogMin, float fogRange, float fogDensity);
|
||||||
|
float exponentialSquaredFog(float x, float fogStart, float fogLength, float fogMin, float fogRange, float fogDensity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//======//
|
||||||
|
// main //
|
||||||
|
//======//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fragment shader for fog.
|
||||||
|
* This should be run last so it applies above other affects like Ambient Occlusioning
|
||||||
|
*/
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float fragmentDepth = texture(uDhDepthTexture, TexCoord).r;
|
||||||
|
fragColor = vec4(uFogColor.rgb, 0.0);
|
||||||
|
|
||||||
|
// a fragment depth of "1" means the fragment wasn't drawn to,
|
||||||
|
// we only want to apply Fog to LODs, not to the sky outside the LODs
|
||||||
|
if (fragmentDepth < 1.0)
|
||||||
|
{
|
||||||
|
int fogDebugMode = uFogDebugMode;
|
||||||
|
if (fogDebugMode == 0)
|
||||||
|
{
|
||||||
|
// render fog based on distance from the camera
|
||||||
|
vec3 vertexWorldPos = calcViewPosition(fragmentDepth);
|
||||||
|
|
||||||
|
float horizontalWorldDistance = length(vertexWorldPos.xz) * uFogScale;
|
||||||
|
float worldDistance = length(vertexWorldPos.xyz) * uFogScale;
|
||||||
|
float activeDistance = uUseSphericalFog ? worldDistance : horizontalWorldDistance;
|
||||||
|
|
||||||
|
|
||||||
|
// far fog
|
||||||
|
float farFogThickness = getFarFogThickness(activeDistance);
|
||||||
|
|
||||||
|
// height fog
|
||||||
|
float heightFogDepth = calculateHeightFogDepth(vertexWorldPos.y);
|
||||||
|
float heightFogThickness = getHeightFogThickness(heightFogDepth);
|
||||||
|
|
||||||
|
// combined fog
|
||||||
|
float mixedFogThickness = mixFogThickness(farFogThickness, heightFogThickness);
|
||||||
|
fragColor.a = clamp(mixedFogThickness, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
else if (fogDebugMode == 1)
|
||||||
|
{
|
||||||
|
// test code
|
||||||
|
|
||||||
|
// render everything with the fog color
|
||||||
|
fragColor.a = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// test code.
|
||||||
|
|
||||||
|
// this can be fired by manually changing the fullFogMode to a (normally)
|
||||||
|
// invalid value (like 7).
|
||||||
|
// By having a separate if statement defined by
|
||||||
|
// a uniform we don't have to worry about GLSL optimizing away different
|
||||||
|
// options when testing, causing a bunch of headaches if we just want to render the screen red.
|
||||||
|
|
||||||
|
float depthValue = textureLod(uDhDepthTexture, TexCoord, 0).r;
|
||||||
|
fragColor.rgb = vec3(depthValue); // Convert depth value to grayscale color
|
||||||
|
fragColor.a = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper methods //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
vec3 calcViewPosition(float fragmentDepth)
|
||||||
|
{
|
||||||
|
vec4 ndc = vec4(TexCoord.xy, fragmentDepth, 1.0);
|
||||||
|
ndc.xyz = ndc.xyz * 2.0 - 1.0;
|
||||||
|
|
||||||
|
vec4 eyeCoord = uInvMvmProj * ndc;
|
||||||
|
return eyeCoord.xyz / eyeCoord.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// far fog //
|
||||||
|
//=========//
|
||||||
|
|
||||||
|
float getFarFogThickness(float dist)
|
||||||
|
{
|
||||||
|
if (uFogFalloffType == 0) // LINEAR
|
||||||
|
{
|
||||||
|
return linearFog(dist, uFarFogStart, uFarFogLength, uFarFogMin, uFarFogRange);
|
||||||
|
}
|
||||||
|
else if (uFogFalloffType == 1) // EXPONENTIAL
|
||||||
|
{
|
||||||
|
return exponentialFog(dist, uFarFogStart, uFarFogLength, uFarFogMin, uFarFogRange, uFarFogDensity);
|
||||||
|
}
|
||||||
|
else // EXPONENTIAL_SQUARED
|
||||||
|
{
|
||||||
|
return exponentialSquaredFog(dist, uFarFogStart, uFarFogLength, uFarFogMin, uFarFogRange, uFarFogDensity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float getHeightFogThickness(float dist)
|
||||||
|
{
|
||||||
|
if (!uHeightFogEnabled)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uHeightFogFalloffType == 0) // LINEAR
|
||||||
|
{
|
||||||
|
return linearFog(dist, uHeightFogStart, uHeightFogLength, uHeightFogMin, uHeightFogRange);
|
||||||
|
}
|
||||||
|
else if (uHeightFogFalloffType == 1) // EXPONENTIAL
|
||||||
|
{
|
||||||
|
return exponentialFog(dist, uHeightFogStart, uHeightFogLength, uHeightFogMin, uHeightFogRange, uHeightFogDensity);
|
||||||
|
}
|
||||||
|
else // EXPONENTIAL_SQUARED
|
||||||
|
{
|
||||||
|
return exponentialSquaredFog(dist, uHeightFogStart, uHeightFogLength, uHeightFogMin, uHeightFogRange, uHeightFogDensity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float linearFog(float worldDist, float fogStart, float fogLength, float fogMin, float fogRange)
|
||||||
|
{
|
||||||
|
worldDist = (worldDist - fogStart) / fogLength;
|
||||||
|
worldDist = clamp(worldDist, 0.0, 1.0);
|
||||||
|
return fogMin + fogRange * worldDist;
|
||||||
|
}
|
||||||
|
|
||||||
|
float exponentialFog(
|
||||||
|
float x, float fogStart, float fogLength,
|
||||||
|
float fogMin, float fogRange, float fogDensity)
|
||||||
|
{
|
||||||
|
x = max((x-fogStart)/fogLength, 0.0) * fogDensity;
|
||||||
|
return fogMin + fogRange - fogRange/exp(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
float exponentialSquaredFog(
|
||||||
|
float x, float fogStart, float fogLength,
|
||||||
|
float fogMin, float fogRange, float fogDensity)
|
||||||
|
{
|
||||||
|
x = max((x-fogStart)/fogLength, 0.0) * fogDensity;
|
||||||
|
return fogMin + fogRange - fogRange/exp(x*x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============//
|
||||||
|
// height fog //
|
||||||
|
//============//
|
||||||
|
|
||||||
|
/** 1 = full fog, 0 = no fog */
|
||||||
|
float calculateHeightFogDepth(float worldYPos)
|
||||||
|
{
|
||||||
|
// worldYPos -65 - 384
|
||||||
|
|
||||||
|
|
||||||
|
//worldYPos = worldYPos * -1; // negative, fog below height; positive, fog above height
|
||||||
|
//return worldYPos * uFogVerticalScale; // "* uFogVerticalScale" is done to convert world position to a percent of the world height;
|
||||||
|
|
||||||
|
if (!uHeightFogEnabled)
|
||||||
|
{
|
||||||
|
// ignore the height
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!uHeightBasedOnCamera)
|
||||||
|
{
|
||||||
|
worldYPos -= (uHeightFogBaseHeight - uCameraBlockYPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (uHeightFogAppliesDown && uHeightFogAppliesUp)
|
||||||
|
{
|
||||||
|
return abs(worldYPos) * uFogVerticalScale;
|
||||||
|
}
|
||||||
|
else if (uHeightFogAppliesDown)
|
||||||
|
{
|
||||||
|
// apploy fog below given height
|
||||||
|
return -worldYPos * uFogVerticalScale;
|
||||||
|
}
|
||||||
|
else if (uHeightFogAppliesUp)
|
||||||
|
{
|
||||||
|
// apply fog above given height
|
||||||
|
return worldYPos * uFogVerticalScale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// shouldn't happen,
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float mixFogThickness(float far, float height)
|
||||||
|
{
|
||||||
|
switch (uHeightFogMixingMode)
|
||||||
|
{
|
||||||
|
case 0: // BASIC
|
||||||
|
case 1: // IGNORE_HEIGHT
|
||||||
|
return far;
|
||||||
|
|
||||||
|
case 2: // MAX
|
||||||
|
return max(far, height);
|
||||||
|
|
||||||
|
case 3: // ADDITION
|
||||||
|
return (far + height);
|
||||||
|
|
||||||
|
case 4: // MULTIPLY
|
||||||
|
return far * height;
|
||||||
|
|
||||||
|
case 5: // INVERSE_MULTIPLY
|
||||||
|
return (1.0 - (1.0-far)*(1.0-height));
|
||||||
|
|
||||||
|
case 6: // LIMITED_ADDITION
|
||||||
|
return (far + max(far, height));
|
||||||
|
|
||||||
|
case 7: // MULTIPLY_ADDITION
|
||||||
|
return (far + far*height);
|
||||||
|
|
||||||
|
case 8: // INVERSE_MULTIPLY_ADDITION
|
||||||
|
return (far + 1.0 - (1.0-far)*(1.0-height));
|
||||||
|
|
||||||
|
case 9: // AVERAGE
|
||||||
|
return (far*0.5 + height*0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// shouldn't happen, but default to BASIC / IGNORE_HEIGHT
|
||||||
|
// if an invalid option is selected
|
||||||
|
return far;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#version 150 core
|
||||||
|
|
||||||
|
in vec2 vPosition;
|
||||||
|
|
||||||
|
out vec2 TexCoord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is specifically used by application shaders.
|
||||||
|
* IE post process or pixel transfer shaders, anything that is rendered using a single rectangle.
|
||||||
|
*/
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(vPosition, 1.0, 1.0);
|
||||||
|
TexCoord = vPosition.xy * 0.5 + 0.5;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user