202 lines
5.4 KiB
Plaintext
202 lines
5.4 KiB
Plaintext
#version 120
|
|
const float tau = 6.28318530716;
|
|
const bool parallax = #{{level:extreme}};
|
|
const bool advancedProcedurals = #{{level:high}};
|
|
|
|
// it needs special tweaks to not bleed out in overexposure
|
|
bool lightShaftsOn = #{{bGodRays}};
|
|
bool bloomOn = #{{bBloom}};
|
|
|
|
// parallax scale, bias and steps
|
|
const vec2 scaleBias = vec2(0.005, 0.0025);
|
|
|
|
uniform sampler2D texture[2];
|
|
uniform float cycles[5];
|
|
uniform float temperature;
|
|
uniform float nodeScale;
|
|
|
|
varying float distortion;
|
|
varying vec2 uvA, uvB;
|
|
varying vec3 vertCol, normal, origo;
|
|
varying vec3 v;
|
|
|
|
const float maxVariance = 0.03; //should be kept low
|
|
const float deviationCycles = 3.25; //How much variation is based on base color
|
|
|
|
const float two_pi = 6.28318531;
|
|
|
|
const float noise1Base = 0.84, noise1Range = 0.25;
|
|
const float noise2Base = 0.93, noise2Range = 0.34;
|
|
|
|
const float diffPower = 2.3;
|
|
const float tempInfluence = 0.25;
|
|
const float baseTemp = 10000.0;
|
|
|
|
const float noiseOffsetNoise = 0.1;
|
|
|
|
float mixRange(float x, float low, float hi) {
|
|
return clamp((x - low) / (hi - low), 0.0, 1.0);
|
|
}
|
|
|
|
vec3 blackBody(float temp) {
|
|
vec3 c;
|
|
c.r = mix(1.0, 0.6234, mixRange(temp, 6400.0, 29800.0));
|
|
c.b = mix(0.0, 1.0, mixRange(temp, 2800.0, 7600.0));
|
|
if(temp < 6600.0)
|
|
c.g = mix(0.22, 0.976, mixRange(temp, 1000.0, 6600.0));
|
|
else
|
|
c.g = mix(0.976, 0.75, mixRange(temp, 6600.0, 29800.0));
|
|
if(temp > 13000.0)
|
|
c += vec3(mixRange(temp, 13000.0, 29800.0));
|
|
return c;
|
|
}
|
|
|
|
vec3 dp1Calc(vec3 p)
|
|
{
|
|
return dFdx(p);
|
|
}
|
|
|
|
vec3 dp2Calc(vec3 p)
|
|
{
|
|
return dFdy(p);
|
|
}
|
|
|
|
vec4 duv1Calc(vec4 uv)
|
|
{
|
|
return dFdx(uv);
|
|
}
|
|
|
|
vec4 duv2Calc(vec4 uv)
|
|
{
|
|
return dFdy(uv);
|
|
}
|
|
float pow4(float x){
|
|
x*= x;
|
|
return x*x;
|
|
}
|
|
/*
|
|
float mip_map_level(vec2 uv)
|
|
{
|
|
|
|
vec2 dx_vtc = dFdx(uv);
|
|
vec2 dy_vtc = dFdy(uv);
|
|
float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
|
|
|
|
|
|
//return max(0.0, 0.5 * log2(delta_max_sqr) - 1.0); // == log2(sqrt(delta_max_sqr));
|
|
return 0.5 * log2(delta_max_sqr); // == log2(sqrt(delta_max_sqr));
|
|
}
|
|
*/
|
|
float starSampMip(vec2 uv, float mip){
|
|
vec2 noiseCoord = uv * 3.0 + (texture2D(texture[1], uv * 16.0, mip).xz - vec2(0.5)) * noiseOffsetNoise;
|
|
noiseCoord += vec2( cycles[0], cycles[1]);
|
|
|
|
vec2 noise2Coord = noiseCoord + vec2( -cycles[3], cycles[4] );
|
|
vec2 noise3Coord = noiseCoord + vec2( -cycles[2], cycles[3] * 4.0 );
|
|
vec2 noise4Coord = noiseCoord * 2.0 + vec2( cycles[4], cycles[0] * -2.0 );
|
|
|
|
noiseCoord += vec2( cycles[1], cycles[2] );
|
|
float heat = noise1Base + noise1Range *
|
|
texture2D(texture[1], uv * 4.0, mip).r;
|
|
heat *= noise2Base + noise2Range *
|
|
texture2D(texture[0], noise2Coord, mip).g;
|
|
heat *= noise2Base + noise2Range *
|
|
texture2D(texture[0], noise3Coord, mip).b;
|
|
heat *= noise1Base + noise1Range *
|
|
texture2D(texture[1], noise4Coord, mip).g;
|
|
|
|
return heat;
|
|
}
|
|
|
|
float starSamp(vec2 uv){
|
|
vec2 noiseCoord =uv * 3.0 + (texture2D(texture[1], uv * 16.0).xz - vec2(0.5)) * noiseOffsetNoise;
|
|
noiseCoord += vec2( cycles[0], cycles[1]);
|
|
|
|
vec2 noise2Coord = noiseCoord + vec2( -cycles[3], cycles[4] );
|
|
vec2 noise3Coord = noiseCoord + vec2( -cycles[2], cycles[3] * 4.0 );
|
|
vec2 noise4Coord = noiseCoord * 2.0 + vec2( cycles[4], cycles[0] * -2.0 );
|
|
|
|
noiseCoord += vec2( cycles[1], cycles[2] );
|
|
|
|
float heat = noise1Base + noise1Range *
|
|
texture2D(texture[1], uv * 4.0).r;
|
|
heat *= noise2Base + noise2Range *
|
|
texture2D(texture[0], noise2Coord).g;
|
|
heat *= noise2Base + noise2Range *
|
|
texture2D(texture[0], noise3Coord).b;
|
|
heat *= noise1Base + noise1Range *
|
|
texture2D(texture[1], noise4Coord).g;
|
|
|
|
return heat;
|
|
}
|
|
void main() {
|
|
vec4 uvP = vec4(uvA, uvB);
|
|
// do polar blend mask from world space normals
|
|
float blendMask = clamp(abs(normal.y)* 4.0 - 2.0, 0.0, 1.0);
|
|
|
|
float NdotV = max(0.0, dot(normal, v));
|
|
|
|
float heat = 0.0;
|
|
|
|
if (parallax){
|
|
// star surface to noisy to work for parallax, so sample mip-blurred for approximate softened plumes
|
|
heat = mix(starSampMip(uvB, 5.0), starSampMip(uvA, 5.0), blendMask);
|
|
// make the parallax a little more interesting
|
|
heat = pow4(abs(fract(heat) * 2.0 - 1.0));
|
|
// and smoothstep
|
|
heat *= heat * (3.0 - (2.0 * heat));
|
|
|
|
vec3 dp1 = dp1Calc(-v);
|
|
vec3 dp2 = dp2Calc(-v);
|
|
|
|
// derive for both uv's
|
|
vec4 duv1 = duv1Calc(uvP);
|
|
vec4 duv2 = duv2Calc(uvP);
|
|
|
|
vec3 dp2perp = cross(dp2, normal);
|
|
vec3 dp1perp = cross(normal, dp1);
|
|
|
|
// do parallax
|
|
float fDet = dot(dp1, dp2perp);
|
|
vec2 vProjVScr = (1.0/fDet) * vec2(dot(dp2perp, v), dot(dp1perp, v));
|
|
vec4 vProjVTex = (duv1 * vProjVScr.x + duv2 * vProjVScr.y);
|
|
float vProjVTexZ = NdotV * ((1.0 - heat - 0.5) * scaleBias.r - scaleBias.g);
|
|
|
|
uvP += (vProjVTex * vProjVTexZ);
|
|
|
|
heat = mix(starSamp(uvP.zw), starSamp(uvP.xy), blendMask);
|
|
}
|
|
else{
|
|
heat = mix(starSamp(uvB), starSamp(uvA), blendMask);
|
|
}
|
|
heat -=1.1;
|
|
|
|
|
|
if(temperature < 3500.0) {
|
|
heat += 0.05;
|
|
if(heat < 0.0)
|
|
heat *= 2.0;
|
|
else
|
|
heat *= 22.0 - (temperature / 350.0);
|
|
}
|
|
else if(temperature < 6500.0) {
|
|
heat *= 4.0;
|
|
}
|
|
else if(temperature > 20000.0) {
|
|
heat *= 5.0;
|
|
}
|
|
else {
|
|
heat += 0.05;
|
|
if(heat < 0.0)
|
|
heat *= 2.0;
|
|
else
|
|
heat *= 20.0;
|
|
}
|
|
|
|
heat = mix(heat, 0.7, pow(max(distortion,0.0), 2.8));
|
|
heat = mix(0.6, heat, NdotV) + 1.0;
|
|
|
|
gl_FragColor.rgb = blackBody(temperature * heat) * clamp(heat, min(temperature / 2500.0, 1.0), 1.0);
|
|
gl_FragColor.a = 1.0;
|
|
}
|