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.RenderBufferHandler;
|
||||
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.objects.SortedArraySet;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
@@ -148,6 +149,7 @@ public class McLodRenderer
|
||||
|
||||
IMcLodRenderer lodRenderer = SingletonInjector.INSTANCE.get(IMcLodRenderer.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.
|
||||
|| renderParams.vanillaFogEnabled)
|
||||
{
|
||||
//profiler.popPush("LOD Fog");
|
||||
//
|
||||
//Mat4f combinedMatrix = new Mat4f(renderParams.dhProjectionMatrix);
|
||||
//combinedMatrix.multiply(renderParams.dhModelViewMatrix);
|
||||
//
|
||||
//FogRenderer.INSTANCE.render(combinedMatrix, renderParams.partialTicks);
|
||||
profiler.popPush("LOD Fog");
|
||||
|
||||
Mat4f combinedMatrix = new Mat4f(renderParams.dhProjectionMatrix);
|
||||
combinedMatrix.multiply(renderParams.dhModelViewMatrix);
|
||||
|
||||
fogRenderer.render(combinedMatrix, renderParams.partialTicks);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -243,9 +243,9 @@ public class FogShader extends AbstractShaderRenderer
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
+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