openclonk/planet/Graphics.ocg/LandscapeShader.glsl

127 lines
3.9 KiB
GLSL

// Input textures
uniform sampler2D landscapeTex[2];
uniform sampler2D scalerTex;
uniform sampler3D materialTex;
// Resolution of the landscape texture
uniform vec2 resolution;
// Center position
uniform vec2 center;
// Texture map
uniform sampler1D matMapTex;
uniform int materialDepth;
uniform vec2 materialSize;
// Expected parameters for the scaler
const vec2 scalerStepX = vec2(1.0 / 8.0, 0.0);
const vec2 scalerStepY = vec2(0.0, 1.0 / 32.0);
const vec2 scalerOffset = scalerStepX / 3.0 + scalerStepY / 3.0;
const vec2 scalerPixel = vec2(scalerStepX.x, scalerStepY.y) / 3.0;
// How much % the normals from the normal map are added up to the
// landscape normal. The higher the strength, the more structure
// within the material is visible but also the less the borders
// between the different materials stand out.
const float normalMapStrength = 0.20;
vec4 queryMatMap(int pix)
{
return texture1D(matMapTex, float(pix) / 2.0 / 256.0 + 0.5 / 2.0 / 256.0);
}
slice(coordinate)
{
// full pixel steps in the landscape texture (depends on landscape resolution)
vec2 fullStep = vec2(1.0, 1.0) / resolution;
vec2 fullStepX = vec2(fullStep.x, 0.0);
vec2 fullStepY = vec2(0.0, fullStep.y);
vec2 texCoo = gl_TexCoord[0].st;
// calculate pixel position in landscape, find center of current pixel
vec2 pixelCoo = texCoo * resolution;
vec2 centerCoo = (floor(pixelCoo) + vec2(0.5, 0.5)) / resolution;
// Texture coordinate for material
vec2 materialCoo = texCoo * resolution / materialSize;
}
slice(texture)
{
// our pixel color (without/with interpolation)
vec4 landscapePx = texture2D(landscapeTex[0], centerCoo);
vec4 realLandscapePx = texture2D(landscapeTex[0], texCoo);
// find scaler coordinate
vec2 scalerCoo = scalerOffset + mod(pixelCoo, vec2(1.0, 1.0)) * scalerPixel;
int iScaler = f2i(landscapePx.a), iRow = iScaler / 8;
scalerCoo.x += float(iScaler - iRow * 8) / 8.0;
scalerCoo.y += float(iScaler / 8) / 32.0;
// query scaler texture
vec4 scalerPx = texture2D(scalerTex, scalerCoo);
// Get "second" landscape pixel
vec2 centerCoo2 = centerCoo + fullStep * floor(vec2(-0.5, -0.5) +
scalerPx.gb * 255.0 / 64.0);
vec4 landscapePx2 = texture2D(landscapeTex[0], centerCoo2);
}
slice(material)
{
// Get material properties from material map
int matMapIx = f2i(landscapePx.r);
vec4 matMap = queryMatMap(2*matMapIx);
vec4 matMapX = queryMatMap(2*matMapIx+1);
float materialIx = float(f2i(matMap.a)) / 256.0 + 0.5 / float(materialDepth);
vec3 matEmit = matMap.rgb;
vec3 matSpot = matMapX.rgb * 255.9f / 16.0f;
float matAngle = matMapX.a;
// Query material texture pixels
vec4 materialPx = texture3D(materialTex, vec3(materialCoo, materialIx));
vec4 normalPx = texture3D(materialTex, vec3(materialCoo, materialIx+0.5));
// Same for second pixel
int matMapIx2 = f2i(landscapePx2.r);
vec4 matMap2 = queryMatMap(2*matMapIx2);
vec4 matMapX2 = queryMatMap(2*matMapIx2+1);
float materialIx2 = float(f2i(matMap2.a)) / 256.0 + 0.5 / float(materialDepth);
vec3 matEmit2 = matMap2.rgb;
vec3 matSpot2 = matMapX2.rgb * 255.9f / 16.0f;
float matAngle2 = matMapX2.a;
// Query material texture pixels
vec4 materialPx2 = texture3D(materialTex, vec3(materialCoo, materialIx2));
vec4 normalPx2 = texture3D(materialTex, vec3(materialCoo, materialIx2+0.5));
}
slice(normal)
{
// Normal calculation
vec3 normal = extend_normal(1.5 * (mix(realLandscapePx.yz, landscapePx.yz, scalerPx.a)
- vec2(0.5, 0.5)));
vec3 textureNormal = normalPx.xyz - vec3(0.5,0.5,0.5);
normal = mix(textureNormal, normal, normalMapStrength);
vec3 normal2 = extend_normal(landscapePx2.yz - vec2(0.5, 0.5));
vec3 textureNormal2 = normalPx2.xyz - vec3(0.5,0.5,0.5);
normal2 = mix(textureNormal2, normal2, normalMapStrength);
}
slice(color) {
#define color gl_FragColor
color = materialPx;
vec4 color2 = materialPx2;
}
slice(color+10) {
// Mix second color into main color according to scaler
color = mix(color2, color, scalerPx.r);
}