mirror of
https://github.com/Ttanasart-pt/Pixel-Composer.git
synced 2025-01-14 08:16:34 +01:00
118 lines
3.5 KiB
GLSL
118 lines
3.5 KiB
GLSL
#define MATRIX_VIEW 0
|
|
#define MATRIX_PROJECTION 1
|
|
#define MATRIX_WORLD 2
|
|
#define MATRIX_WORLD_VIEW 3
|
|
#define MATRIX_WORLD_VIEW_PROJECTION 4
|
|
#define MATRICES_MAX 5
|
|
|
|
uniform mat4 gm_Matrices[MATRICES_MAX];
|
|
|
|
uniform bool gm_LightingEnabled;
|
|
uniform bool gm_VS_FogEnabled;
|
|
uniform float gm_FogStart;
|
|
uniform float gm_RcpFogRange;
|
|
|
|
#define MAX_VS_LIGHTS 8
|
|
#define MIRROR_WIN32_LIGHTING_EQUATION
|
|
|
|
|
|
//#define MAX_VS_LIGHTS 8
|
|
uniform vec4 gm_AmbientColour; // rgb=colour, a=1
|
|
uniform vec4 gm_Lights_Direction[MAX_VS_LIGHTS]; // normalised direction
|
|
uniform vec4 gm_Lights_PosRange[MAX_VS_LIGHTS]; // X,Y,Z position, W range
|
|
uniform vec4 gm_Lights_Colour[MAX_VS_LIGHTS]; // rgb=colour, a=1
|
|
|
|
float CalcFogFactor(vec4 pos)
|
|
{
|
|
if (gm_VS_FogEnabled)
|
|
{
|
|
vec4 viewpos = gm_Matrices[MATRIX_WORLD_VIEW] * pos;
|
|
float fogfactor = ((viewpos.z - gm_FogStart) * gm_RcpFogRange);
|
|
return fogfactor;
|
|
}
|
|
else
|
|
{
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
vec4 DoDirLight(vec3 ws_normal, vec4 dir, vec4 diffusecol)
|
|
{
|
|
float dotresult = dot(ws_normal, dir.xyz);
|
|
dotresult = min(dotresult, dir.w); // the w component is 1 if the directional light is active, or 0 if it isn't
|
|
dotresult = max(0.0, dotresult);
|
|
|
|
return dotresult * diffusecol;
|
|
}
|
|
|
|
vec4 DoPointLight(vec3 ws_pos, vec3 ws_normal, vec4 posrange, vec4 diffusecol)
|
|
{
|
|
vec3 diffvec = ws_pos - posrange.xyz;
|
|
float veclen = length(diffvec);
|
|
diffvec /= veclen; // normalise
|
|
float atten;
|
|
if (posrange.w == 0.0) // the w component of posrange is 0 if the point light is disabled - if we don't catch it here we might end up generating INFs or NaNs
|
|
{
|
|
atten = 0.0;
|
|
}
|
|
else
|
|
{
|
|
#ifdef MIRROR_WIN32_LIGHTING_EQUATION
|
|
// This is based on the Win32 D3D and OpenGL falloff model, where:
|
|
// Attenuation = 1.0f / (factor0 + (d * factor1) + (d*d * factor2))
|
|
// For some reason, factor0 is set to 0.0f while factor1 is set to 1.0f/lightrange (on both D3D and OpenGL)
|
|
// This'll result in no visible falloff as 1.0f / (d / lightrange) will always be larger than 1.0f (if the vertex is within range)
|
|
|
|
atten = 1.0 / (veclen / posrange.w);
|
|
if (veclen > posrange.w)
|
|
{
|
|
atten = 0.0;
|
|
}
|
|
#else
|
|
atten = clamp( (1.0 - (veclen / posrange.w)), 0.0, 1.0); // storing 1.0f/range instead would save a rcp
|
|
#endif
|
|
}
|
|
float dotresult = dot(ws_normal, diffvec);
|
|
dotresult = max(0.0, dotresult);
|
|
|
|
return dotresult * atten * diffusecol;
|
|
}
|
|
|
|
vec4 DoLighting(vec4 vertexcolour, vec4 objectspacepos, vec3 objectspacenormal)
|
|
{
|
|
if (gm_LightingEnabled)
|
|
{
|
|
// Normally we'd have the light positions\\directions back-transformed from world to object space
|
|
// But to keep things simple for the moment we'll just transform the normal to world space
|
|
vec4 objectspacenormal4 = vec4(objectspacenormal, 0.0);
|
|
vec3 ws_normal;
|
|
ws_normal = (gm_Matrices[MATRIX_WORLD] * objectspacenormal4).xyz;
|
|
ws_normal = normalize(ws_normal);
|
|
|
|
vec3 ws_pos;
|
|
ws_pos = (gm_Matrices[MATRIX_WORLD] * objectspacepos).xyz;
|
|
|
|
// Accumulate lighting from different light types
|
|
vec4 accumcol = vec4(0.0, 0.0, 0.0, 0.0);
|
|
for(int i = 0; i < MAX_VS_LIGHTS; i++)
|
|
{
|
|
accumcol += DoDirLight(ws_normal, gm_Lights_Direction[i], gm_Lights_Colour[i]);
|
|
}
|
|
|
|
for(int i = 0; i < MAX_VS_LIGHTS; i++)
|
|
{
|
|
accumcol += DoPointLight(ws_pos, ws_normal, gm_Lights_PosRange[i], gm_Lights_Colour[i]);
|
|
}
|
|
|
|
accumcol *= vertexcolour;
|
|
accumcol += gm_AmbientColour;
|
|
accumcol = min(vec4(1.0, 1.0, 1.0, 1.0), accumcol);
|
|
accumcol.a = vertexcolour.a;
|
|
return accumcol;
|
|
}
|
|
else
|
|
{
|
|
return vertexcolour;
|
|
}
|
|
}
|
|
|