022f22173b
git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@2054 127b21dd-08f5-0310-b4b7-95ae10353056
364 lines
9.4 KiB
Plaintext
364 lines
9.4 KiB
Plaintext
/*
|
||
oolite-default-shader.fragment
|
||
Default fragment shader for Oolite ships.
|
||
|
||
This is similar to normal ship shaders, but has special controlling
|
||
macros (like OOSTD_DIFFUSE_MAP, OOSTD_SPECULAR etc.) which are specific
|
||
to the default shader.
|
||
|
||
A note on the structure of this file: the GLSL implementation on Mac OS X
|
||
10.4.x can't handle shaders with nested #if/#ifdefs on some systems. I
|
||
haven't explored this in detail, but it seems to be PowerPC-specific.
|
||
Avoiding such nesting while dealing with several controlling macros leads
|
||
to this rather messy code structure.
|
||
This bug is fixed in Mac OS X 10.5.
|
||
|
||
|
||
© 2007–2008 Jens Ayton
|
||
|
||
This program is free software; you can redistribute it and/or
|
||
modify it under the terms of the GNU General Public License
|
||
as published by the Free Software Foundation; either version 2
|
||
of the License, or (at your option) any later version.
|
||
|
||
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 General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program; if not, write to the Free Software
|
||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||
MA 02110-1301, USA.
|
||
|
||
|
||
This file may also be distributed under the MIT/X11 license:
|
||
|
||
Copyright © 2007–2008 Jens Ayton
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all
|
||
copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
SOFTWARE.
|
||
*/
|
||
|
||
|
||
#ifndef OOSTD_DIFFUSE_MAP
|
||
#define OOSTD_DIFFUSE_MAP 0
|
||
#endif
|
||
|
||
#ifndef OOSTD_SPECULAR
|
||
#define OOSTD_SPECULAR 0
|
||
#undef OOSTD_SPECULAR_MAP
|
||
#endif
|
||
|
||
#ifndef OOSTD_SPECULAR_MAP
|
||
#define OOSTD_SPECULAR_MAP 0
|
||
#endif
|
||
|
||
#ifndef OOSTD_NORMAL_MAP
|
||
#define OOSTD_NORMAL_MAP 0
|
||
#endif
|
||
|
||
#ifndef OOSTD_NORMAL_AND_PARALLAX_MAP
|
||
#define OOSTD_NORMAL_AND_PARALLAX_MAP 0
|
||
#endif
|
||
|
||
#ifndef OOSTD_EMISSION
|
||
#define OOSTD_EMISSION 0
|
||
#endif
|
||
|
||
#ifndef OOSTD_EMISSION_MAP
|
||
#define OOSTD_EMISSION_MAP 0
|
||
#endif
|
||
|
||
#ifndef OOSTD_ILLUMINATION_MAP
|
||
#define OOSTD_ILLUMINATION_MAP 0
|
||
#endif
|
||
|
||
#ifndef OOSTD_EMISSION_AND_ILLUMINATION_MAP
|
||
#define OOSTD_EMISSION_AND_ILLUMINATION_MAP 0
|
||
#endif
|
||
|
||
#ifndef OO_LIGHT_0_FIX
|
||
#define OO_LIGHT_0_FIX 0
|
||
#endif
|
||
|
||
|
||
#if OOSTD_EMISSION_AND_ILLUMINATION_MAP && !OOSTD_EMISSION_MAP
|
||
#undef OOSTD_EMISSION_MAP
|
||
#define OOSTD_EMISSION_MAP 1
|
||
#endif
|
||
#if OOSTD_EMISSION_AND_ILLUMINATION_MAP && OOSTD_ILLUMINATION_MAP
|
||
#undef OOSTD_EMISSION_AND_ILLUMINATION_MAP
|
||
#define OOSTD_EMISSION_AND_ILLUMINATION_MAP 0
|
||
#endif
|
||
#if OOSTD_NORMAL_AND_PARALLAX_MAP && !OOSTD_NORMAL_MAP
|
||
#undef OOSTD_NORMAL_AND_PARALLAX_MAP
|
||
#define OOSTD_NORMAL_AND_PARALLAX_MAP 0
|
||
#endif
|
||
|
||
|
||
#if OOSTD_SPECULAR
|
||
#define NEED_EYE_VECTOR 1
|
||
#else
|
||
#define NEED_EYE_VECTOR 0
|
||
#endif
|
||
|
||
#if OOSTD_EMISSION_AND_ILLUMINATION_MAP || OOSTD_ILLUMINATION_MAP
|
||
#define HAVE_ILLUMINATION 1
|
||
#else
|
||
#define HAVE_ILLUMINATION 0
|
||
#endif
|
||
|
||
|
||
#if NEED_EYE_VECTOR
|
||
varying vec3 vEyeVector;
|
||
#endif
|
||
|
||
varying vec2 vTexCoord;
|
||
|
||
#if OO_LIGHT_0_FIX
|
||
varying vec3 vLight0Vector;
|
||
#endif
|
||
varying vec3 vLight1Vector;
|
||
|
||
|
||
#if OOSTD_DIFFUSE_MAP
|
||
uniform sampler2D uDiffuseMap;
|
||
#endif
|
||
|
||
#if OOSTD_SPECULAR_MAP
|
||
uniform sampler2D uSpecularMap;
|
||
#endif
|
||
|
||
#if OOSTD_NORMAL_MAP
|
||
uniform sampler2D uNormalMap;
|
||
#endif
|
||
|
||
#if OOSTD_EMISSION_MAP
|
||
uniform sampler2D uEmissionMap;
|
||
#endif
|
||
|
||
#if OOSTD_ILLUMINATION_MAP
|
||
uniform sampler2D uIlluminationMap;
|
||
#endif
|
||
|
||
#if OOSTD_NORMAL_AND_PARALLAX_MAP
|
||
uniform float uParallaxScale;
|
||
uniform float uParallaxBias;
|
||
#endif
|
||
|
||
|
||
vec4 CalcDiffuseLight(in vec3 lightVector, in vec3 normal, in vec4 lightColor)
|
||
{
|
||
#if OOSTD_NORMAL_MAP
|
||
float intensity = dot(normal, lightVector);
|
||
#else
|
||
// dot(v, (0,0,1)) is v.x*0 + v.y*0 + v.z*1 = v.z
|
||
float intensity = lightVector.z;
|
||
#endif
|
||
intensity = max(intensity, 0.0);
|
||
return lightColor * intensity;
|
||
}
|
||
|
||
|
||
vec4 CalcSpecularLight(in vec3 lightVector, in vec3 eyeVector, in float exponent, in vec3 normal, in vec4 lightColor)
|
||
{
|
||
#if OOSTD_NORMAL_MAP
|
||
vec3 reflection = -reflect(lightVector, normal);
|
||
#else
|
||
/* reflect(I, N) is defined as I - 2 * dot(N, I) * N
|
||
If N is (0,0,1), this becomes (I.x,I.y,-I.z).
|
||
Note that we want it negated as per above.
|
||
*/
|
||
vec3 reflection = vec3(-lightVector.x, -lightVector.y, lightVector.z);
|
||
#endif
|
||
float intensity = dot(reflection, eyeVector);
|
||
intensity = pow(max(intensity, 0.0), exponent);
|
||
return lightColor * intensity;
|
||
}
|
||
|
||
|
||
#ifndef OO_REDUCED_COMPLEXITY
|
||
uniform float uHullHeatLevel;
|
||
uniform float uTime;
|
||
|
||
|
||
// Irregular flickering function.
|
||
float Pulse(in float value, in float timeScale)
|
||
{
|
||
float t = uTime * timeScale;
|
||
|
||
float s0 = t;
|
||
s0 -= floor(s0);
|
||
float sum = abs( s0 - 0.5);
|
||
|
||
float s1 = t * 0.7 - 0.05;
|
||
s1 -= floor(s1);
|
||
sum += abs(s1 - 0.5) - 0.25;
|
||
|
||
float s2 = t * 1.3 - 0.3;
|
||
s2 -= floor(s2);
|
||
sum += abs(s2 - 0.5) - 0.25;
|
||
|
||
float s3 = t * 5.09 - 0.6;
|
||
s3 -= floor(s3);
|
||
sum += abs(s3 - 0.5) - 0.25;
|
||
|
||
return (sum * 0.1 + 0.9) * value;
|
||
}
|
||
|
||
|
||
// Colour ramp from black through reddish brown/dark orange to yellow-white.
|
||
vec4 TemperatureGlow(in float level)
|
||
{
|
||
vec4 result = vec4(0);
|
||
|
||
result.r = level;
|
||
result.g = level * level * level;
|
||
result.b = max(level - 0.7, 0.0) * 2.0;
|
||
result.a = 1.0;
|
||
|
||
return result;
|
||
}
|
||
#endif
|
||
|
||
|
||
void main(void)
|
||
{
|
||
vec4 totalColor = vec4(0);
|
||
|
||
// Get eye vector
|
||
#if NEED_EYE_VECTOR
|
||
vec3 eyeVector = normalize(vEyeVector);
|
||
#endif
|
||
|
||
// Get texture coords, using parallax mapping if appropriate
|
||
#if OOSTD_NORMAL_AND_PARALLAX_MAP
|
||
float parallax = texture2D(uNormalMap, vTexCoord).a;
|
||
parallax = parallax * uParallaxScale + uParallaxBias;
|
||
vec2 texCoord = vTexCoord - parallax * eyeVector.xy * vec2(-1.0, 1.0);
|
||
#else
|
||
#define texCoord vTexCoord
|
||
#endif
|
||
|
||
// Get normal
|
||
#if OOSTD_NORMAL_MAP
|
||
vec3 normal = texture2D(uNormalMap, texCoord).rgb - 0.5;
|
||
#else
|
||
const vec3 normal = vec3(0.0, 0.0, 1.0);
|
||
#endif
|
||
|
||
// Get light vectors
|
||
#if OO_LIGHT_0_FIX
|
||
vec3 light0Vector = normalize(vLight0Vector);
|
||
#endif
|
||
vec3 light1Vector = normalize(vLight1Vector);
|
||
|
||
// Get ambient colour
|
||
vec4 ambientLight = gl_FrontMaterial.ambient * gl_LightModel.ambient;
|
||
|
||
// Get emission colour
|
||
#if OOSTD_EMISSION || OOSTD_EMISSION_MAP
|
||
vec4 emissionColor = vec4(1.0);
|
||
#endif
|
||
#if OOSTD_EMISSION
|
||
emissionColor *= gl_FrontMaterial.emission;
|
||
#endif
|
||
#if OOSTD_EMISSION_MAP
|
||
vec4 emissionMapColor = texture2D(uEmissionMap, texCoord);
|
||
emissionColor *= emissionMapColor;
|
||
#endif
|
||
#if OOSTD_EMISSION || OOSTD_EMISSION_MAP
|
||
emissionColor.a = 1.0;
|
||
totalColor += emissionColor;
|
||
#endif
|
||
|
||
// Get illumination colour
|
||
#if OOSTD_EMISSION_AND_ILLUMINATION_MAP
|
||
// Use alpha channel of emission map as white illumination
|
||
vec4 illuminationMapLight = vec4(emissionMapColor.aaa, 1.0);
|
||
#elif OOSTD_ILLUMINATION_MAP
|
||
vec4 illuminationMapLight = texture2D(uIlluminationMap, texCoord);
|
||
#endif
|
||
|
||
vec4 diffuseLight = vec4(0);
|
||
#if OO_LIGHT_0_FIX
|
||
diffuseLight += CalcDiffuseLight(light0Vector, normal, gl_LightSource[0].diffuse);
|
||
#endif
|
||
diffuseLight += CalcDiffuseLight(light1Vector, normal, gl_LightSource[1].diffuse);
|
||
|
||
#if HAVE_ILLUMINATION
|
||
diffuseLight += illuminationMapLight;
|
||
#endif
|
||
|
||
// Get specular parameters
|
||
#if OOSTD_SPECULAR_MAP
|
||
vec4 specularMapColor = texture2D(uSpecularMap, texCoord);
|
||
float specularExponentLevel = pow(specularMapColor.a, 2.0) + 0.001;
|
||
specularMapColor.a = 1.0;
|
||
#define APPLY_MAPPED_EXPONENT exponent = (exponent - 1.0) * specularExponentLevel + 1.0
|
||
#else
|
||
#define APPLY_MAPPED_EXPONENT exponent += 0.001
|
||
#endif
|
||
|
||
// Calculate specular light
|
||
#if OOSTD_SPECULAR && OO_LIGHT_0_FIX
|
||
#define SPECULAR_LIGHT_0 specularLight += CalcSpecularLight(light0Vector, eyeVector, exponent, normal, gl_LightSource[0].specular)
|
||
#else
|
||
#define SPECULAR_LIGHT_0
|
||
#endif
|
||
#if OOSTD_SPECULAR
|
||
vec4 specularLight = vec4(0);
|
||
float exponent = gl_FrontMaterial.shininess;
|
||
APPLY_MAPPED_EXPONENT;
|
||
SPECULAR_LIGHT_0;
|
||
specularLight += CalcSpecularLight(light1Vector, eyeVector, exponent, normal, gl_LightSource[1].specular);
|
||
specularLight.a = 1.0;
|
||
#endif
|
||
|
||
vec4 ambientColor = gl_FrontMaterial.ambient;
|
||
vec4 diffuseColor = gl_FrontMaterial.diffuse;
|
||
#if OOSTD_SPECULAR
|
||
vec4 specularColor = gl_FrontMaterial.specular;
|
||
#endif
|
||
#if OOSTD_SPECULAR_MAP
|
||
specularColor *= specularMapColor;
|
||
#endif
|
||
|
||
#if OOSTD_DIFFUSE_MAP
|
||
vec4 diffuseMapColor = texture2D(uDiffuseMap, texCoord);
|
||
diffuseMapColor.a = 1.0;
|
||
diffuseColor *= diffuseMapColor;
|
||
ambientColor *= diffuseMapColor;
|
||
#endif
|
||
|
||
totalColor += ambientColor * ambientLight + diffuseColor * diffuseLight;
|
||
#if OOSTD_SPECULAR
|
||
totalColor += specularColor * specularLight;
|
||
#endif
|
||
|
||
#ifndef OO_REDUCED_COMPLEXITY
|
||
// Heat glow
|
||
float hullHeat = max(uHullHeatLevel - 0.5, 0.0) * 2.0;
|
||
hullHeat = Pulse(hullHeat * hullHeat, 0.1);
|
||
totalColor += TemperatureGlow(hullHeat);
|
||
#endif
|
||
|
||
gl_FragColor = totalColor;
|
||
}
|