mirror of
https://github.com/scratchfoundation/bgfx.git
synced 2024-11-29 11:05:36 -05:00
188 lines
6.5 KiB
Text
188 lines
6.5 KiB
Text
|
vec4 xll_tex2Dlod(sampler2D s, vec4 coord) {
|
||
|
return texture2DLod( s, coord.xy, coord.w);
|
||
|
}
|
||
|
mat3 xll_transpose_mf3x3(mat3 m) {
|
||
|
return mat3( m[0][0], m[1][0], m[2][0],
|
||
|
m[0][1], m[1][1], m[2][1],
|
||
|
m[0][2], m[1][2], m[2][2]);
|
||
|
}
|
||
|
mat3 xll_constructMat3_mf4x4( mat4 m) {
|
||
|
return mat3( vec3( m[0]), vec3( m[1]), vec3( m[2]));
|
||
|
}
|
||
|
struct Lamp {
|
||
|
vec4 posRange;
|
||
|
vec4 colorImp;
|
||
|
vec4 spotParam;
|
||
|
};
|
||
|
struct v2f {
|
||
|
vec4 pos;
|
||
|
vec3 hybridDir;
|
||
|
vec3 hybridCol;
|
||
|
vec3 ambient;
|
||
|
vec2 uv;
|
||
|
};
|
||
|
struct HybridAppData {
|
||
|
vec4 vertex;
|
||
|
vec4 tangent;
|
||
|
vec3 normal;
|
||
|
vec4 texcoord;
|
||
|
vec4 bakedCol;
|
||
|
vec2 bakedDir;
|
||
|
};
|
||
|
uniform vec3 _WorldSpaceCameraPos;
|
||
|
uniform mat4 _Object2World;
|
||
|
uniform mat4 _World2Object;
|
||
|
|
||
|
uniform vec3 _Tonemap_blackLevel;
|
||
|
uniform vec3 _Tonemap_toeLength;
|
||
|
uniform vec3 _Tonemap_heel;
|
||
|
uniform vec3 _Tonemap_shoulder;
|
||
|
uniform vec3 _Tonemap_colorScale1;
|
||
|
uniform vec3 _Tonemap_colorScale2;
|
||
|
uniform vec3 _HybridSunDir;
|
||
|
uniform vec4 _HybridSunCol;
|
||
|
uniform vec3 GridLightTextureStartCell;
|
||
|
uniform vec3 GridLightTextureCellSize;
|
||
|
uniform sampler2D GridLightTexture;
|
||
|
uniform vec4 IngameGridLimit;
|
||
|
uniform vec4 LightPos[30];
|
||
|
uniform vec4 LightCol[30];
|
||
|
uniform vec4 _MainTex_ST;
|
||
|
float Luma( in vec3 c ) {
|
||
|
return dot( c, vec3( 0.22, 0.707, 0.071));
|
||
|
}
|
||
|
void CalcDynamicLight( in vec3 worldVert, in vec3 worldNorm, in Lamp lamp[4], inout vec3 hybridDir, inout vec3 hybridCol )
|
||
|
{
|
||
|
vec3 lAgg = vec3( 0.0);
|
||
|
float wAgg = 0.001;
|
||
|
vec4 atten;
|
||
|
int i = 0;
|
||
|
for ( ; (i < 4); (i++)) {
|
||
|
vec3 lightToVert = (lamp[i].posRange.xyz - worldVert);
|
||
|
float lengthSq = dot( lightToVert, lightToVert);
|
||
|
vec3 lightToVertNorm = (lightToVert * inversesqrt(lengthSq));
|
||
|
atten[i] = max( (1.0 - ((lengthSq * lamp[i].posRange.w) * 0.8)), 0.0);
|
||
|
atten[i] *= atten[i];
|
||
|
float nDotL = max( dot( lightToVertNorm, worldNorm), 0.05);
|
||
|
float weight = ((atten[i] * lamp[i].colorImp.w) * nDotL);
|
||
|
lAgg += (weight * lightToVertNorm);
|
||
|
wAgg += weight;
|
||
|
}
|
||
|
float w = (Luma( hybridCol) * 2.0);
|
||
|
lAgg += (hybridDir * w);
|
||
|
wAgg += w;
|
||
|
hybridDir = (lAgg / wAgg);
|
||
|
int j = 0;
|
||
|
for ( ; (j < 4); (j++)) {
|
||
|
vec3 lightToVertNorm_1 = normalize((lamp[j].posRange.xyz - worldVert));
|
||
|
hybridCol += (lamp[j].colorImp.xyz * atten[j]);
|
||
|
}
|
||
|
}
|
||
|
ivec4 GetLightIdxFromGrid( in vec3 worldVert )
|
||
|
{
|
||
|
vec2 pos = ((worldVert - GridLightTextureStartCell) * GridLightTextureCellSize).xz;
|
||
|
pos = clamp( pos, IngameGridLimit.xy, IngameGridLimit.zw);
|
||
|
return ivec4((xll_tex2Dlod( GridLightTexture, vec4( pos.x, pos.y, 0.0, 0.0)) * 255.0));
|
||
|
}
|
||
|
vec3 DecodeBakedCol( in vec3 bakedCol )
|
||
|
{
|
||
|
vec3 c = (bakedCol * 3.0);
|
||
|
return (c * c);
|
||
|
}
|
||
|
vec3 DecodeNormal( in vec2 enc )
|
||
|
{
|
||
|
vec4 nn = ((enc.xyxy * vec4( 2.0, 2.0, 0.0, 0.0)) + vec4( -1.0, -1.0, 1.01, -1.0));
|
||
|
float l = dot( nn.xyz, (-nn.xyw));
|
||
|
nn.z = l;
|
||
|
nn.xy *= sqrt(l);
|
||
|
return ((nn.xyz * 2.0) + vec3( 0.0, 0.0, -1.0));
|
||
|
}
|
||
|
void DecodeBaking( in vec4 bakedColor, in vec2 bakedDir, out vec3 hybridCol, out vec3 hybridDir )
|
||
|
{
|
||
|
hybridDir = (DecodeNormal( bakedDir) * (bakedColor.w * 2.0));
|
||
|
hybridCol = DecodeBakedCol( bakedColor.xyz);
|
||
|
}
|
||
|
void LoadBakedLight( in vec3 worldVert, in vec3 worldNorm, in vec4 bakedColor, in vec2 bakedDir, out vec3 hybridCol, out vec3 hybridDir )
|
||
|
{
|
||
|
DecodeBaking( bakedColor, bakedDir, hybridCol, hybridDir);
|
||
|
}
|
||
|
void ReadLightArray3( in ivec4 lightIdx, out Lamp l0, out Lamp l1, out Lamp l2, out Lamp l3 )
|
||
|
{
|
||
|
l0.posRange = LightPos[lightIdx.x];
|
||
|
l0.colorImp = LightCol[lightIdx.x];
|
||
|
l0.spotParam = vec4( 0.0, 0.0, 0.0, 1.0);
|
||
|
l1.posRange = LightPos[lightIdx.y];
|
||
|
l1.colorImp = LightCol[lightIdx.y];
|
||
|
l1.spotParam = vec4( 0.0, 0.0, 0.0, 1.0);
|
||
|
l2.posRange = LightPos[lightIdx.z];
|
||
|
l2.colorImp = LightCol[lightIdx.z];
|
||
|
l2.spotParam = vec4( 0.0, 0.0, 0.0, 1.0);
|
||
|
l3.posRange = LightPos[lightIdx.w];
|
||
|
l3.colorImp = LightCol[lightIdx.w];
|
||
|
l3.spotParam = vec4( 0.0, 0.0, 0.0, 1.0);
|
||
|
}
|
||
|
vec3 JimTonemapping( in vec3 x )
|
||
|
{
|
||
|
x = max( (x - (_Tonemap_blackLevel * 0.25)), vec3( 0.0, 0.0, 0.0));
|
||
|
x = ((x * ((_Tonemap_colorScale1 * x) + _Tonemap_heel)) / ((x * ((_Tonemap_colorScale2 * x) + _Tonemap_shoulder)) + _Tonemap_toeLength));
|
||
|
return x;
|
||
|
}
|
||
|
vec3 NichTonemap( in vec3 x )
|
||
|
{
|
||
|
return (JimTonemapping( (x * 0.25)) * 4.0);
|
||
|
float total = (length(x) + 0.0001);
|
||
|
vec3 norm = (x / total);
|
||
|
float tonemapped = (JimTonemapping( vec3( 0.0, (total * 0.25), 0.0)).y * 4.0);
|
||
|
return (norm * tonemapped);
|
||
|
}
|
||
|
vec3 VertexTonemap( in vec3 x )
|
||
|
{
|
||
|
return NichTonemap( x);
|
||
|
}
|
||
|
void DoCalcHybridLight2( in vec3 worldVert, in vec3 worldNorm, out vec3 hybridDir, out vec3 hybridCol, out vec3 ambient, in vec4 bakedColor, in vec2 bakedDir )
|
||
|
{
|
||
|
LoadBakedLight( worldVert, worldNorm, bakedColor, bakedDir, hybridCol, hybridDir);
|
||
|
ivec4 lightIdx = GetLightIdxFromGrid( worldVert);
|
||
|
Lamp l[4];
|
||
|
ReadLightArray3( lightIdx, l[0], l[1], l[2], l[3]);
|
||
|
CalcDynamicLight( worldVert, worldNorm, l, hybridDir, hybridCol);
|
||
|
hybridCol = VertexTonemap( hybridCol);
|
||
|
ambient = VertexTonemap( (_HybridSunCol.xyz * dot( worldNorm, _HybridSunDir)));
|
||
|
}
|
||
|
v2f vert (in HybridAppData v)
|
||
|
{
|
||
|
v2f o;
|
||
|
o.pos = (gl_ModelViewProjectionMatrix * v.vertex);
|
||
|
o.uv = ((v.texcoord.xy * _MainTex_ST.xy) + _MainTex_ST.zw);
|
||
|
vec3 worldVert = (_Object2World * v.vertex).xyz;
|
||
|
vec3 worldNorm = normalize((xll_constructMat3_mf4x4( _Object2World) * v.normal.xyz));
|
||
|
DoCalcHybridLight2( worldVert, worldNorm, o.hybridDir, o.hybridCol, o.ambient, v.bakedCol, v.bakedDir);
|
||
|
vec3 eyeToVert = normalize((_WorldSpaceCameraPos.xyz - worldVert));
|
||
|
vec3 binormal = (cross( v.normal, v.tangent.xyz) * v.tangent.w);
|
||
|
mat3 rotation = xll_transpose_mf3x3(mat3( v.tangent.xyz, binormal, v.normal));
|
||
|
o.hybridDir = (rotation * (xll_constructMat3_mf4x4( _World2Object) * o.hybridDir));
|
||
|
return o;
|
||
|
}
|
||
|
attribute vec4 TANGENT;
|
||
|
varying vec3 xlv_TEXCOORD0;
|
||
|
varying vec3 xlv_TEXCOORD1;
|
||
|
varying vec3 xlv_COLOR;
|
||
|
varying vec2 xlv_TEXCOORD2;
|
||
|
void main()
|
||
|
{
|
||
|
v2f xl_retval;
|
||
|
HybridAppData xlt_v;
|
||
|
xlt_v.vertex = vec4(gl_Vertex);
|
||
|
xlt_v.tangent = vec4(TANGENT);
|
||
|
xlt_v.normal = vec3(gl_Normal);
|
||
|
xlt_v.texcoord = vec4(gl_MultiTexCoord0);
|
||
|
xlt_v.bakedCol = vec4(gl_Color);
|
||
|
xlt_v.bakedDir = vec2(gl_MultiTexCoord1);
|
||
|
xl_retval = vert( xlt_v);
|
||
|
gl_Position = vec4(xl_retval.pos);
|
||
|
xlv_TEXCOORD0 = vec3(xl_retval.hybridDir);
|
||
|
xlv_TEXCOORD1 = vec3(xl_retval.hybridCol);
|
||
|
xlv_COLOR = vec3(xl_retval.ambient);
|
||
|
xlv_TEXCOORD2 = vec2(xl_retval.uv);
|
||
|
}
|