Merge pull request #434 from jaquadro/fix-fog-render

Fog: water, mix order, precision, post-processing
This commit is contained in:
Adubbz 2015-03-24 16:17:48 +11:00
commit cce44a3910

View file

@ -1,11 +1,10 @@
package biomesoplenty.client.fog;
import biomesoplenty.common.configuration.BOPConfigurationMisc;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
@ -13,6 +12,7 @@ import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.potion.Potion;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraftforge.client.event.EntityViewRenderEvent;
@ -20,7 +20,6 @@ import net.minecraftforge.client.event.EntityViewRenderEvent.FogColors;
import net.minecraftforge.common.ForgeModContainer;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
@ -43,10 +42,25 @@ public class FogHandler
int y = MathHelper.floor_double(player.posY);
int z = MathHelper.floor_double(player.posZ);
int oldColour = ((int)(event.red * 255) & 255) << 16 | ((int)(event.green * 255) & 255) << 8 | (int)(event.blue * 255) & 255;
int colour = getFogBlendColour(world, player, x, y, z, oldColour, event.renderPartialTicks);
Block blockAtEyes = ActiveRenderInfo.getBlockAtEntityViewpoint(world, event.entity, (float)event.renderPartialTicks);
if (blockAtEyes.getMaterial() == Material.lava)
{
return;
}
event.red = (colour >> 16 & 255) / 255.0F; event.green = (colour >> 8 & 255) / 255.0F; event.blue = (colour & 255) / 255.0F;
Vec3 mixedColor;
if (blockAtEyes.getMaterial() == Material.water)
{
mixedColor = getFogBlendColorWater(world, player, x, y, z, event.renderPartialTicks);
}
else
{
mixedColor = getFogBlendColour(world, player, x, y, z, event.red, event.green, event.blue, event.renderPartialTicks);
}
event.red = (float)mixedColor.xCoord;
event.green = (float)mixedColor.yCoord;
event.blue = (float)mixedColor.zCoord;
}
}
@ -150,7 +164,125 @@ public class FogHandler
}
}
public static int getFogBlendColour(World world, Entity playerEntity, int playerX, int playerY, int playerZ, int defaultColour, double renderPartialTicks)
private static Vec3 postProcessColor (World world, EntityLivingBase player, float r, float g, float b, double renderPartialTicks)
{
double darkScale = (player.lastTickPosY + (player.posY - player.lastTickPosY) * renderPartialTicks) * world.provider.getVoidFogYFactor();
if (player.isPotionActive(Potion.blindness))
{
int duration = player.getActivePotionEffect(Potion.blindness).getDuration();
darkScale *= (duration < 20) ? (1 - duration / 20f) : 0;
}
if (darkScale < 1)
{
darkScale = (darkScale < 0) ? 0 : darkScale * darkScale;
r *= darkScale;
g *= darkScale;
b *= darkScale;
}
if (player.isPotionActive(Potion.nightVision))
{
// Get night vision brightness, accounting for wavering at end of potion effect
int duration = player.getActivePotionEffect(Potion.nightVision).getDuration();
float brightness = (duration > 200) ? 1 : 0.7f + MathHelper.sin((float)((duration - renderPartialTicks) * Math.PI * 0.2f)) * 0.3f;
// Find scale to bring r, g, or b to 1.0
// Vanilla will actually set the colors to +Infinity if all components are 0, explaining the terrible
// interaction between the blindness and night vision potion effects.
float scale = 1 / r;
scale = Math.min(scale, 1 / g);
scale = Math.min(scale, 1 / b);
r = r * (1 - brightness) + r * scale * brightness;
g = g * (1 - brightness) + g * scale * brightness;
b = b * (1 - brightness) + b * scale * brightness;
}
if (Minecraft.getMinecraft().gameSettings.anaglyph)
{
float aR = (r * 30 + g * 59 + b * 11) / 100;
float aG = (r * 30 + g * 70) / 100;
float aB = (r * 30 + b * 70) / 100;
r = aR;
g = aG;
b = aB;
}
return Vec3.createVectorHelper(r, g, b);
}
private static Vec3 getFogBlendColorWater (World world, EntityLivingBase playerEntity, int playerX, int playerY, int playerZ, double renderPartialTicks)
{
int distance = 2;
float rBiomeFog = 0;
float gBiomeFog = 0;
float bBiomeFog = 0;
for (int x = -distance; x <= distance; ++x)
{
for (int z = -distance; z <= distance; ++z)
{
BiomeGenBase biome = world.getBiomeGenForCoords(playerX + x, playerZ + z);
int waterColorMult = biome.waterColorMultiplier;
float rPart = (waterColorMult & 0xFF0000) >> 16;
float gPart = (waterColorMult & 0x00FF00) >> 8;
float bPart = waterColorMult & 0x0000FF;
if (x == -distance)
{
double xDiff = 1 - (playerEntity.posX - playerX);
rPart *= xDiff;
gPart *= xDiff;
bPart *= xDiff;
}
else if (x == distance)
{
double xDiff = playerEntity.posX - playerX;
rPart *= xDiff;
gPart *= xDiff;
bPart *= xDiff;
}
if (z == -distance)
{
double zDiff = 1 - (playerEntity.posZ - playerZ);
rPart *= zDiff;
gPart *= zDiff;
bPart *= zDiff;
}
else if (z == distance)
{
double zDiff = playerEntity.posZ - playerZ;
rPart *= zDiff;
gPart *= zDiff;
bPart *= zDiff;
}
rBiomeFog += rPart;
gBiomeFog += gPart;
bBiomeFog += bPart;
}
}
rBiomeFog /= 255f;
gBiomeFog /= 255f;
bBiomeFog /= 255f;
float weight = (distance * 2) * (distance * 2);
float respirationLevel = (float)EnchantmentHelper.getRespiration(playerEntity) * 0.2F;
float rMixed = (rBiomeFog * 0.02f + respirationLevel) / weight;
float gMixed = (gBiomeFog * 0.02f + respirationLevel) / weight;
float bMixed = (bBiomeFog * 0.2f + respirationLevel) / weight;
return postProcessColor(world, playerEntity, rMixed, gMixed, bMixed, renderPartialTicks);
}
private static Vec3 getFogBlendColour(World world, EntityLivingBase playerEntity, int playerX, int playerY, int playerZ, float defR, float defG, float defB, double renderPartialTicks)
{
GameSettings settings = Minecraft.getMinecraft().gameSettings;
int[] ranges = ForgeModContainer.blendRanges;
@ -223,6 +355,15 @@ public class FogHandler
}
}
if (weightBiomeFog == 0)
{
return Vec3.createVectorHelper(defR, defG, defB);
}
rBiomeFog /= 255f;
gBiomeFog /= 255f;
bBiomeFog /= 255f;
// Calculate day / night / weather scale for BiomeFog component
float celestialAngle = world.getCelestialAngle((float)renderPartialTicks);
float baseScale = MathHelper.clamp_float(MathHelper.cos(celestialAngle * (float)Math.PI * 2.0F) * 2.0F + 0.5F, 0, 1);
@ -245,20 +386,24 @@ public class FogHandler
bScale *= 1 - thunderStrength * 0.5f;
}
// Mix default fog component with BiomeFog component
float rDefault = (defaultColour & 0xFF0000) >> 16;
float gDefault = (defaultColour & 0x00FF00) >> 8;
float bDefault = defaultColour & 0x0000FF;
// Apply post-processing to BiomeFog component. Default color was already processed by Vanilla.
rBiomeFog *= rScale / weightBiomeFog;
gBiomeFog *= gScale / weightBiomeFog;
bBiomeFog *= bScale / weightBiomeFog;
Vec3 processedColor = postProcessColor(world, playerEntity, rBiomeFog, gBiomeFog, bBiomeFog, renderPartialTicks);
rBiomeFog = (float)processedColor.xCoord;
gBiomeFog = (float)processedColor.yCoord;
bBiomeFog = (float)processedColor.zCoord;
// Mix default fog component with BiomeFog component
float weightMixed = (distance * 2) * (distance * 2);
float weightDefault = weightMixed - weightBiomeFog;
float rMixed = (rBiomeFog * rScale + rDefault * weightDefault) / weightMixed;
float gMixed = (gBiomeFog * gScale + gDefault * weightDefault) / weightMixed;
float bMixed = (bBiomeFog * bScale + bDefault * weightDefault) / weightMixed;
processedColor.xCoord = (rBiomeFog * weightBiomeFog + defR * weightDefault) / weightMixed;
processedColor.yCoord = (gBiomeFog * weightBiomeFog + defG * weightDefault) / weightMixed;
processedColor.zCoord = (bBiomeFog * weightBiomeFog + defB * weightDefault) / weightMixed;
int multiplier = ((int)rMixed & 255) << 16 | ((int)gMixed & 255) << 8 | (int)bMixed & 255;
return multiplier;
return processedColor;
}
}