Skip to content

Commit

Permalink
* Adds procedural fog. Variation is based on the daytime and a noise …
Browse files Browse the repository at this point in the history
…function

Fog gets stronger during sunrise and dawn but is limited during the night. During the daytime it can get quite foggy… So be careful. ;)
* Replaces costly sine functions with Crytek's sine/cosine approximations
* Restores colored grass block textures
Make sure to deleted the cached files in your SAVED_WORLDS directory
* Adjusts shaders to color grass blocks correctly
* Tweaks lighting so everything is correctly lit again (and not too dark)
* Tweaks lighting to look nicer
* Adds some various other tweaks…
  • Loading branch information
begla committed Jun 18, 2012
1 parent a8d7fb0 commit f4c4ac4
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 29 deletions.
6 changes: 6 additions & 0 deletions src/main/java/org/terasology/logic/world/IWorldProvider.java
Expand Up @@ -20,6 +20,7 @@
import org.terasology.logic.simulators.GrowthSimulator;
import org.terasology.logic.simulators.LiquidSimulator;
import org.terasology.utilities.FastRandom;
import org.terasology.utilities.PerlinNoise;

import javax.vecmath.Tuple3i;
import javax.vecmath.Vector3d;
Expand Down Expand Up @@ -272,6 +273,11 @@ public interface IWorldProvider {
*/
public FastRandom getRandom();

/**
*
*/
public PerlinNoise getPerlinGenerator();

/**
* Disposes this world provider.
*/
Expand Down
Expand Up @@ -42,6 +42,7 @@
import org.terasology.model.structures.BlockPosition;
import org.terasology.persistence.PersistableObject;
import org.terasology.utilities.FastRandom;
import org.terasology.utilities.PerlinNoise;

/**
* Provides basic support for generating worlds.
Expand Down Expand Up @@ -75,6 +76,7 @@ public class LocalWorldProvider extends PersistableObject implements IWorldProvi

/* RANDOMNESS */
protected final FastRandom _random;
PerlinNoise _perlinGenerator;

/**
* Initializes a new world.
Expand Down Expand Up @@ -102,6 +104,7 @@ public LocalWorldProvider(String title, String seed) {

// Init. random generator
_random = new FastRandom(seed.hashCode());
_perlinGenerator = new PerlinNoise(seed.hashCode());

_generatorManager = new GeneratorManager(this);
_chunkProvider = new ChunkProvider(this);
Expand Down Expand Up @@ -536,6 +539,11 @@ public FastRandom getRandom() {
return _random;
}

@Override
public PerlinNoise getPerlinGenerator() {
return _perlinGenerator;
}

@Override
public String getTitle() {
return _title;
Expand Down
Expand Up @@ -27,10 +27,12 @@
import org.terasology.logic.manager.Config;
import org.terasology.logic.manager.PostProcessingRenderer;
import org.terasology.logic.world.IWorldProvider;
import org.terasology.math.TeraMath;
import org.terasology.model.blocks.Block;
import org.terasology.model.blocks.management.BlockManager;
import org.terasology.rendering.assets.Texture;
import org.terasology.rendering.world.WorldRenderer;
import org.terasology.utilities.PerlinNoise;

/**
* Shader parameters for the Post-processing shader program.
Expand Down Expand Up @@ -64,6 +66,30 @@ public void applyParameters(ShaderProgram program) {

program.setFloat("viewingDistance", Config.getInstance().getActiveViewingDistance() * 8.0f);

// Calculate the fog value based on the daylight value
float fogIntensity = 0.0f;
float daylight = (float) CoreRegistry.get(WorldRenderer.class).getDaylight();

if (daylight < 1.0 && daylight > 0.25)
{
float daylightFactor = (1.0f - daylight) / 0.75f;
fogIntensity = 0.5f * daylightFactor;
}
else if (daylight <= 0.25f)
{
float daylightFactor = (0.25f - daylight) / 0.25f;
fogIntensity = TeraMath.lerpf(0.5f, 0.1f, daylightFactor);
}

WorldRenderer renderer = CoreRegistry.get(WorldRenderer.class);

// TODO: This should be a bit more sophisticated
//fogIntensity = (float) TeraMath.clamp(fogIntensity + renderer.getActiveHumidity(new Vector3d(renderer.getPlayer().getPosition())));

fogIntensity = fogIntensity + (float) TeraMath.clamp(renderer.getWorldProvider().getPerlinGenerator().noise(renderer.getWorldProvider().getTime() * 4.0 ,0.038291,0.874691) * 15.0 * daylight, 0.0, 15.0) + 0.05f;

program.setFloat("fogIntensity", fogIntensity);

if (CoreRegistry.get(LocalPlayer.class).isValid()) {
Vector3d cameraPos = CoreRegistry.get(WorldRenderer.class).getActiveCamera().getPosition();
byte blockId = CoreRegistry.get(IWorldProvider.class).getBlockAtPosition(cameraPos);
Expand Down
Expand Up @@ -55,7 +55,7 @@ public class Skysphere implements IGameObject {
private static final float PI = 3.1415926f;

/* SKY */
private double _turbidity = 6.0f, _sunPosAngle = 0.1f;
private double _turbidity = 4.0f, _sunPosAngle = 0.1f;

/* CLOUDS */
private static final Vector2f CLOUD_RESOLUTION = Config.getInstance().getCloudResolution();
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 39 additions & 18 deletions src/main/resources/org/terasology/data/shaders/chunk_frag.glsl
Expand Up @@ -37,6 +37,20 @@ uniform vec2 waterCoordinate;
uniform vec2 lavaCoordinate;
uniform vec2 grassCoordinate;

#define DAYLIGHT_AMBIENT_COLOR 1.0, 0.9, 0.9
#define MOONLIGHT_AMBIENT_COLOR 0.8, 0.8, 1.0
#define NIGHT_BRIGHTNESS 0.25
#define WATER_COLOR 0.325, 0.819, 0.925, 0.3

#define TORCH_WATER_SPEC 0.8
#define TORCH_WATER_DIFF 0.7
#define TORCH_BLOCK_SPEC 0.5
#define TORCH_BLOCK_DIFF 0.7
#define WATER_SPEC 1.0
#define WATER_DIFF 1.0
#define BLOCK_DIFF 0.25
#define BLOCK_AMB 1.0

void main(){
vec4 texCoord = gl_TexCoord[0];

Expand All @@ -47,8 +61,8 @@ void main(){
vec3 finalLightDir = lightDir;

/* DAYLIGHT BECOMES... MOONLIGHT! */
if (daylight <= 0.0)
finalLightDir *= -1.0;
/* Now featuring linear interpolation to make the transition more smoothly... :-) */
finalLightDir = mix(finalLightDir * -1.0, finalLightDir, daylight);

vec4 color;

Expand All @@ -57,13 +71,13 @@ void main(){
vec2 waterOffset = vec2(vertexWorldPosRaw.x + timeToTick(time, 0.1), vertexWorldPosRaw.z) / 16.0;
normalWater = (texture2D(textureWaterNormal, waterOffset) * 2.0 - 1.0).xyz;

color = vec4(83.0 / 255.0, 209.0 / 255.0, 236.0 / 255.0, 0.5);
color = vec4(WATER_COLOR);
isWater = true;
/* APPLY LAVA TEXTURE */
} else if (texCoord.x >= lavaCoordinate.x && texCoord.x < lavaCoordinate.x + TEXTURE_OFFSET && texCoord.y >= lavaCoordinate.y && texCoord.y < lavaCoordinate.y + TEXTURE_OFFSET) {
texCoord.x = mod(texCoord.x, TEXTURE_OFFSET) * (1.0 / TEXTURE_OFFSET);
texCoord.y = mod(texCoord.y, TEXTURE_OFFSET) / (128.0 / (1.0 / TEXTURE_OFFSET));
texCoord.y += mod(timeToTick(time, 0.1),127.0) * (1.0/128.0);
texCoord.y += mod(timeToTick(time, 0.1), 127.0) * (1.0/128.0);

color = texture2D(textureLava, texCoord.xy);
/* APPLY DEFAULT TEXTURE FROM ATLAS */
Expand All @@ -79,13 +93,20 @@ void main(){

/* APPLY OVERALL BIOME COLOR OFFSET */
if (!(texCoord.x >= grassCoordinate.x && texCoord.x < grassCoordinate.x + TEXTURE_OFFSET && texCoord.y >= grassCoordinate.y && texCoord.y < grassCoordinate.y + TEXTURE_OFFSET)) {
color.rgb *= gl_Color.rgb;
color.a *= gl_Color.a;
if (gl_Color.rgb != vec3(1.0)) {
color.rgb = color.r * gl_Color.rgb;
color.a *= gl_Color.a;
}
else {
color.rgb *= gl_Color.rgb;
color.a *= gl_Color.a;
}
/* MASK GRASS AND APPLY BIOME COLOR */
} else {
vec4 maskColor = texture2D(textureEffects, vec2(10.0 * TEXTURE_OFFSET + mod(texCoord.x,TEXTURE_OFFSET), mod(texCoord.y,TEXTURE_OFFSET)));

if (maskColor.a != 0.0) color.rgb *= gl_Color.rgb;
// Only use one channel so the color won't be altered
if (maskColor.a != 0.0) color.rgb = color.r * gl_Color.rgb;
}

// Calculate daylight lighting value
Expand All @@ -111,42 +132,42 @@ void main(){
/* CALCULATE TORCHLIGHT */
if (carryingTorch) {
if (isWater)
torchlight = calcTorchlight(calcLambLight(normalWater, normalizedVPos) * 0.1
+ 0.9 * calcSpecLightWithOffset(normal, normalizedVPos, normalize(eyeVec), 64.0, normalWater), vertexWorldPos.xyz);
torchlight = calcTorchlight(calcLambLight(normalWater, normalizedVPos) * TORCH_WATER_DIFF
+ TORCH_WATER_SPEC * calcSpecLightWithOffset(normal, normalizedVPos, normalize(eyeVec), 64.0, normalWater), vertexWorldPos.xyz);
else
torchlight = calcTorchlight(calcLambLight(normal, normalizedVPos) * 0.9
+ 0.1 * calcSpecLight(normal, normalizedVPos, normalize(eyeVec), 32.0), vertexWorldPos.xyz);
torchlight = calcTorchlight(calcLambLight(normal, normalizedVPos) * TORCH_BLOCK_DIFF
+ TORCH_BLOCK_SPEC * calcSpecLight(normal, normalizedVPos, normalize(eyeVec), 32.0), vertexWorldPos.xyz);
}

vec3 daylightColorValue;

/* CREATE THE DAYLIGHT LIGHTING MIX */
if (isWater) {
/* WATER NEEDS DIFFUSE AND SPECULAR LIGHT */
daylightColorValue = vec3(diffuseLighting);
daylightColorValue += calcSpecLightWithOffset(normal, finalLightDir, normalize(eyeVec), 64.0, normalWater);
daylightColorValue = vec3(diffuseLighting) * WATER_DIFF;
daylightColorValue += calcSpecLightWithOffset(normal, finalLightDir, normalize(eyeVec), 64.0, normalWater) * WATER_SPEC;
} else {
/* DEFAULT LIGHTING ONLY CONSIST OF DIFFUSE AND AMBIENT LIGHT */
daylightColorValue = vec3(1.0 + diffuseLighting * 0.25);
daylightColorValue = vec3(BLOCK_AMB + diffuseLighting * BLOCK_DIFF);
}

/* SUNLIGHT BECOMES MOONLIGHT */
vec3 ambientTint = mix(vec3(0.8, 0.8, 1.0), vec3(1.0, 0.99, 0.99), daylight);
vec3 ambientTint = mix(vec3(MOONLIGHT_AMBIENT_COLOR), vec3(DAYLIGHT_AMBIENT_COLOR), daylight);
daylightColorValue.xyz *= ambientTint;

// Scale the lighting according to the daylight and daylight block values and add moonlight during the nights
daylightColorValue.xyz *= daylightScaledValue + (0.25 * (1.0 - daylight) * daylightValue);
daylightColorValue.xyz *= daylightScaledValue + (NIGHT_BRIGHTNESS * (1.0 - daylight) * daylightValue);

// Calculate the final block light brightness
float blockBrightness = (blocklightValue * 0.8 + diffuseLighting * blocklightValue * 0.2);
float blockBrightness = (blocklightValue + diffuseLighting * blocklightValue);

torchlight -= flickering;
if (torchlight < 0.0)
torchlight = 0.0;

blockBrightness += (1.0 - blockBrightness) * torchlight;
blockBrightness -= flickering * blocklightValue;
blockBrightness *= blocklightDayIntensity * 0.75;
blockBrightness *= blocklightDayIntensity;

if (blockBrightness < 0.0)
blockBrightness = 0.0;
Expand Down
16 changes: 9 additions & 7 deletions src/main/resources/org/terasology/data/shaders/chunk_vert.glsl
Expand Up @@ -28,6 +28,8 @@ uniform vec2 waterCoordinate;
uniform vec2 lavaCoordinate;
uniform vec3 chunkOffset;

#define ANIMATION_DISTANCE 1024 // sqr(32)

void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
Expand All @@ -43,33 +45,33 @@ void main()
normal = gl_NormalMatrix * gl_Normal;
gl_FrontColor = gl_Color;

float distance = length(vertexWorldPos);
float distance = vertexWorldPos.x * vertexWorldPos.x + vertexWorldPos.y * vertexWorldPos.y + vertexWorldPos.z * vertexWorldPos.z;

#ifdef FLICKERING_LIGHT
flickering = (sin(timeToTick(time, 1.0) + 1.0) / 32.0);
flickering = (smoothTriangleWave(timeToTick(time, 0.2) + 1.0) / 32.0);
#else
flickering = 0.0;
#endif

#ifdef ANIMATED_WATER_AND_GRASS
vec3 vertexChunkPos = vertexWorldPosRaw.xyz + chunkOffset.xyz;

if (distance < 64.0) {
if (distance < ANIMATION_DISTANCE) {
// GRASS ANIMATION
for (int i=0; i < 32; i+=2) {
if (gl_TexCoord[0].x >= wavingCoordinates[i] && gl_TexCoord[0].x < wavingCoordinates[i] + TEXTURE_OFFSET && gl_TexCoord[0].y >= wavingCoordinates[i+1] && gl_TexCoord[0].y < wavingCoordinates[i+1] + TEXTURE_OFFSET) {
if (gl_TexCoord[0].y < wavingCoordinates[i+1] + TEXTURE_OFFSET / 2.0) {
vertexWorldPos.x += sin(timeToTick(time, 1.0) + vertexChunkPos.x) * 0.3;
vertexWorldPos.y += sin(timeToTick(time, 0.5) + vertexChunkPos.x) * 0.1;
vertexWorldPos.x += smoothTriangleWave(timeToTick(time, 0.15) + vertexChunkPos.x * 0.1 + vertexChunkPos.z * 0.1) * 0.25;
vertexWorldPos.y += smoothTriangleWave(timeToTick(time, 0.05) + vertexChunkPos.x * 0.1 + vertexChunkPos.z * 0.1) * 0.2;
}
}
}
}

if (gl_TexCoord[0].x >= waterCoordinate.x && gl_TexCoord[0].x < waterCoordinate.x + TEXTURE_OFFSET && gl_TexCoord[0].y >= waterCoordinate.y && gl_TexCoord[0].y < waterCoordinate.y + TEXTURE_OFFSET) {
vertexWorldPos.y += sin(timeToTick(time, 1.0) + vertexChunkPos.x + + vertexChunkPos.z) * sin(timeToTick(time, 0.5) + vertexChunkPos.x + vertexChunkPos.z + 16.0) * 0.1;
vertexWorldPos.y += smoothTriangleWave(timeToTick(time, 0.1) + vertexChunkPos.x * 0.1 + vertexChunkPos.z * 0.1) * 0.1 + smoothTriangleWave(timeToTick(time, 0.05) + vertexChunkPos.x * 0.1 + vertexChunkPos.z * 0.1) * 0.2;
} else if (gl_TexCoord[0].x >= lavaCoordinate.x && gl_TexCoord[0].x < lavaCoordinate.x + TEXTURE_OFFSET && gl_TexCoord[0].y >= lavaCoordinate.y && gl_TexCoord[0].y < lavaCoordinate.y + TEXTURE_OFFSET) {
vertexWorldPos.y += sin(timeToTick(time, 0.5) + vertexChunkPos.x + vertexChunkPos.z) * 0.1;
vertexWorldPos.y += smoothTriangleWave(timeToTick(time, 0.05) + vertexChunkPos.x * 0.1 + vertexChunkPos.z * 0.1) * 0.2;
}
#endif

Expand Down
Expand Up @@ -17,3 +17,15 @@
float timeToTick(float time, float speed) {
return time * 4000.0 * speed;
}

// Crytek fast sin/cos approximations

float smoothCurve( float x ) {
return x * x * ( 3.0 - 2.0 * x );
}
float triangleWave( float x ) {
return abs( fract( x + 0.5 ) * 2.0 - 1.0 );
}
float smoothTriangleWave( float x ) {
return smoothCurve( triangleWave( x ) ) * 2.0 - 1.0 ;
}
2 changes: 2 additions & 0 deletions src/main/resources/org/terasology/data/shaders/post_frag.glsl
Expand Up @@ -22,6 +22,7 @@ uniform sampler2D texDepth;

uniform bool swimming;

uniform float fogIntensity = 0.1;
uniform float viewingDistance;

#define Z_NEAR 0.1
Expand Down Expand Up @@ -54,6 +55,7 @@ void main() {

/* FINAL MIX */
vec4 finalColor = mix(color, colorBlur, blur);
finalColor = mix(finalColor, vec4(1.0), 1.0 - 1.0 / pow(2.71828, depth * fogIntensity));

/* VIGNETTE */
float vig = texture2D(texVignette, gl_TexCoord[0].xy).x;
Expand Down
Expand Up @@ -23,7 +23,7 @@ uniform vec4 sunPos;
uniform samplerCube texCube;

vec4 eyePos = vec4(0.0, 0.0, 0.0, 1.0);
float colorExp = 8.0;
float colorExp = 12.0;

vec3 convertColor() {
if (colorYxy == vec3(0.0, 0.0, 0.0))
Expand Down
2 changes: 0 additions & 2 deletions src/main/resources/org/terasology/data/shaders/sky_vert.glsl
Expand Up @@ -25,8 +25,6 @@ uniform vec3 zenith;

vec4 eyePos = vec4(0.0, 0.0, 0.0, 1.0);

#define EPS 0.1

vec3 allweather ( float t, float cosTheta, float cosGamma )
{
float gamma = acos ( cosGamma );
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f4c4ac4

Please sign in to comment.