Update REMDER (Dx9)
This commit is contained in:
59
FLARDATA/Shader/ColorConversion.inc
Normal file
59
FLARDATA/Shader/ColorConversion.inc
Normal file
@@ -0,0 +1,59 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//
|
||||
//Color conversion include shader for FLAR by Schmackbolzen
|
||||
|
||||
vec3 ToLinearAccurate(vec3 inColor)
|
||||
{
|
||||
vec3 treshold=step(vec3(0.04045),inColor);
|
||||
return mix(inColor / 12.92,pow ((inColor + 0.055) / 1.055, vec3(2.4)),treshold);
|
||||
}
|
||||
|
||||
vec3 ToGammaCorrectedAccurate(vec3 inColor)
|
||||
{
|
||||
vec3 treshold=step(vec3(0.0031308),inColor);
|
||||
return mix(inColor * 12.92,pow (inColor, vec3(1.0/2.4)) * 1.055 - 0.055,treshold);
|
||||
}
|
||||
|
||||
vec3 ToLinearFast(vec3 inColor)
|
||||
{
|
||||
return pow(inColor,vec3(2.2));
|
||||
}
|
||||
|
||||
vec3 ToGammaCorrectedFast(vec3 inColor)
|
||||
{
|
||||
return pow(inColor.rgb,1./vec3(2.2));
|
||||
}
|
||||
|
||||
$SRGB_CONVERSION_DEFINE
|
||||
#ifdef ALWAYS_USE_FAST_SRGB_CONVERSION
|
||||
vec3 ToLinear(vec3 inColor)
|
||||
{
|
||||
return ToLinearFast(inColor);
|
||||
}
|
||||
|
||||
vec3 ToGammaCorrected(vec3 inColor)
|
||||
{
|
||||
return ToGammaCorrectedFast(inColor);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ALWAYS_USE_ACCURATE_SRGB_CONVERSION
|
||||
vec3 ToLinear(vec3 inColor)
|
||||
{
|
||||
return ToLinearAccurate(inColor);
|
||||
}
|
||||
|
||||
vec3 ToGammaCorrected(vec3 inColor)
|
||||
{
|
||||
return ToGammaCorrectedAccurate(inColor);
|
||||
}
|
||||
#endif
|
||||
|
||||
//Works on gamma compressed and linear values (note that the values are not identical)
|
||||
//Values are from https://en.wikipedia.org/wiki/Luma_(video)
|
||||
float ToLuma(vec3 color)
|
||||
{
|
||||
return dot(color, vec3(0.2126, 0.7152f, 0.0722f));
|
||||
}
|
||||
47
FLARDATA/Shader/Irradiance.fp
Normal file
47
FLARDATA/Shader/Irradiance.fp
Normal file
@@ -0,0 +1,47 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Code based on https://learnopengl.com/PBR/IBL/Specular-IBL
|
||||
|
||||
#version 330
|
||||
#include "ColorConversion.inc"
|
||||
in vec3 WorldPos;
|
||||
|
||||
uniform samplerCube environmentMap;
|
||||
uniform bool convertToLinear;
|
||||
|
||||
const float PI = 3.14159265359;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 N = normalize(WorldPos);
|
||||
|
||||
vec3 irradiance = vec3(0.0);
|
||||
|
||||
// tangent space calculation from origin point
|
||||
vec3 up = vec3(0.0, 1.0, 0.0);
|
||||
vec3 right = normalize(cross(up, N));
|
||||
up = normalize(cross(N, right));
|
||||
|
||||
float sampleDelta = 0.025;
|
||||
float nrSamples = 0.0f;
|
||||
for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta)
|
||||
{
|
||||
for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta)
|
||||
{
|
||||
// spherical to cartesian (in tangent space)
|
||||
vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
|
||||
// tangent space to world
|
||||
vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N;
|
||||
|
||||
vec3 texColor=texture(environmentMap, sampleVec).rgb;
|
||||
if(convertToLinear)
|
||||
texColor=ToLinear(texColor);
|
||||
irradiance += texColor * cos(theta) * sin(theta);
|
||||
nrSamples++;
|
||||
}
|
||||
}
|
||||
irradiance = PI * irradiance * (1.0 / float(nrSamples));
|
||||
|
||||
gl_FragColor = vec4(ToGammaCorrected(irradiance), 1.0);
|
||||
}
|
||||
81
FLARDATA/Shader/bloomDownsample.fs
Normal file
81
FLARDATA/Shader/bloomDownsample.fs
Normal file
@@ -0,0 +1,81 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//
|
||||
//PBR bloom downsample shader for FLAR by Schmackbolzen based on code from https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom
|
||||
//The code has been modified to be more like the original presentation and also blog article from the original
|
||||
//authors of the technique (referenced in the link above).
|
||||
|
||||
#version 330
|
||||
#include "ColorConversion.inc"
|
||||
|
||||
uniform sampler2D srcTexture;
|
||||
uniform vec2 srcTexelSize[$NUM_MIPS];
|
||||
|
||||
|
||||
uniform int mipLevel;
|
||||
|
||||
in vec2 texCoord;
|
||||
layout (location = 0) out vec3 downsample;
|
||||
|
||||
float KarisAverage(vec3 col)
|
||||
{
|
||||
// Formula is 1 / (1 + luma)
|
||||
float luma = ToLuma(col);
|
||||
return 1.0f / (1.0f + luma);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texelSize = srcTexelSize[mipLevel];
|
||||
float x = texelSize.x;
|
||||
float y = texelSize.y;
|
||||
|
||||
// Take 13 samples around current texel:
|
||||
// a - b - c
|
||||
// - j - k -
|
||||
// d - e - f
|
||||
// - l - m -
|
||||
// g - h - i
|
||||
// === ('e' is the current texel) ===
|
||||
vec3 a = texture(srcTexture, vec2(texCoord.x - 2*x, texCoord.y + 2*y)).rgb;
|
||||
vec3 b = texture(srcTexture, vec2(texCoord.x, texCoord.y + 2*y)).rgb;
|
||||
vec3 c = texture(srcTexture, vec2(texCoord.x + 2*x, texCoord.y + 2*y)).rgb;
|
||||
|
||||
vec3 d = texture(srcTexture, vec2(texCoord.x - 2*x, texCoord.y)).rgb;
|
||||
vec3 e = texture(srcTexture, vec2(texCoord.x, texCoord.y)).rgb;
|
||||
vec3 f = texture(srcTexture, vec2(texCoord.x + 2*x, texCoord.y)).rgb;
|
||||
|
||||
vec3 g = texture(srcTexture, vec2(texCoord.x - 2*x, texCoord.y - 2*y)).rgb;
|
||||
vec3 h = texture(srcTexture, vec2(texCoord.x, texCoord.y - 2*y)).rgb;
|
||||
vec3 i = texture(srcTexture, vec2(texCoord.x + 2*x, texCoord.y - 2*y)).rgb;
|
||||
|
||||
vec3 j = texture(srcTexture, vec2(texCoord.x - x, texCoord.y + y)).rgb;
|
||||
vec3 k = texture(srcTexture, vec2(texCoord.x + x, texCoord.y + y)).rgb;
|
||||
vec3 l = texture(srcTexture, vec2(texCoord.x - x, texCoord.y - y)).rgb;
|
||||
vec3 m = texture(srcTexture, vec2(texCoord.x + x, texCoord.y - y)).rgb;
|
||||
|
||||
vec3 groups[5];
|
||||
const float factor1=0.125f/4.f;
|
||||
const float factor2=0.5f/4.f;
|
||||
groups[0] = (a+b+d+e) * factor1;
|
||||
groups[1] = (b+c+e+f) * factor1;
|
||||
groups[2] = (d+e+g+h) * factor1;
|
||||
groups[3] = (e+f+h+i) * factor1;
|
||||
groups[4] = (j+k+l+m) * factor2;
|
||||
if (mipLevel == 0)
|
||||
{
|
||||
float avg1=KarisAverage(groups[0]);
|
||||
float avg2=KarisAverage(groups[1]);
|
||||
float avg3=KarisAverage(groups[2]);
|
||||
float avg4=KarisAverage(groups[3]);
|
||||
float avg5=KarisAverage(groups[4]);
|
||||
float normalization=avg1+avg2+avg3+avg4+avg5+0.0001;
|
||||
downsample = (groups[0]*avg1+groups[1]*avg2+groups[2]*avg3+groups[3]*avg4+groups[4]*avg5)/normalization;
|
||||
downsample = max(downsample, 0.0001f);
|
||||
}
|
||||
else
|
||||
{
|
||||
downsample = (groups[0]+groups[1]+groups[2]+groups[3]+groups[4]);
|
||||
}
|
||||
}
|
||||
18
FLARDATA/Shader/bloomDownsample.vs
Normal file
18
FLARDATA/Shader/bloomDownsample.vs
Normal file
@@ -0,0 +1,18 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//
|
||||
//PBR bloom downsample shader for FLAR by Schmackbolzen based on code from https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom
|
||||
|
||||
#version 330
|
||||
|
||||
layout (location = 0) in vec2 aPosition;
|
||||
layout (location = 1) in vec2 aTexCoord;
|
||||
|
||||
out vec2 texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(aPosition.x, aPosition.y, 0.0, 1.0);
|
||||
texCoord = aTexCoord;
|
||||
}
|
||||
46
FLARDATA/Shader/bloomUpsample.fs
Normal file
46
FLARDATA/Shader/bloomUpsample.fs
Normal file
@@ -0,0 +1,46 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//
|
||||
//PBR bloom upsample shader for FLAR by Schmackbolzen based on code from https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom
|
||||
//The only bug fix is using different filter radii for each direction since the texture is not square
|
||||
|
||||
#version 330
|
||||
uniform sampler2D srcTexture;
|
||||
uniform float filterRadiusX;
|
||||
uniform float filterRadiusY;
|
||||
|
||||
in vec2 texCoord;
|
||||
layout (location = 0) out vec3 upsample;
|
||||
|
||||
void main()
|
||||
{
|
||||
float x = filterRadiusX;
|
||||
float y = filterRadiusY;
|
||||
|
||||
// Take 9 samples around current texel:
|
||||
// a - b - c
|
||||
// d - e - f
|
||||
// g - h - i
|
||||
// === ('e' is the current texel) ===
|
||||
vec3 a = texture(srcTexture, vec2(texCoord.x - x, texCoord.y + y)).rgb;
|
||||
vec3 b = texture(srcTexture, vec2(texCoord.x, texCoord.y + y)).rgb;
|
||||
vec3 c = texture(srcTexture, vec2(texCoord.x + x, texCoord.y + y)).rgb;
|
||||
|
||||
vec3 d = texture(srcTexture, vec2(texCoord.x - x, texCoord.y)).rgb;
|
||||
vec3 e = texture(srcTexture, vec2(texCoord.x, texCoord.y)).rgb;
|
||||
vec3 f = texture(srcTexture, vec2(texCoord.x + x, texCoord.y)).rgb;
|
||||
|
||||
vec3 g = texture(srcTexture, vec2(texCoord.x - x, texCoord.y - y)).rgb;
|
||||
vec3 h = texture(srcTexture, vec2(texCoord.x, texCoord.y - y)).rgb;
|
||||
vec3 i = texture(srcTexture, vec2(texCoord.x + x, texCoord.y - y)).rgb;
|
||||
|
||||
// Apply weighted distribution, by using a 3x3 tent filter:
|
||||
// 1 | 1 2 1 |
|
||||
// -- * | 2 4 2 |
|
||||
// 16 | 1 2 1 |
|
||||
upsample = e*4.0;
|
||||
upsample += (b+d+f+h)*2.0;
|
||||
upsample += (a+c+g+i);
|
||||
upsample *= 1.0 / 16.0;
|
||||
}
|
||||
18
FLARDATA/Shader/bloomUpsample.vs
Normal file
18
FLARDATA/Shader/bloomUpsample.vs
Normal file
@@ -0,0 +1,18 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//
|
||||
//PBR bloom upsample shader for FLAR by Schmackbolzen based on code from https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom
|
||||
|
||||
#version 330
|
||||
|
||||
layout (location = 0) in vec2 aPosition;
|
||||
layout (location = 1) in vec2 aTexCoord;
|
||||
|
||||
out vec2 texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(aPosition.x, aPosition.y, 0.0, 1.0);
|
||||
texCoord = aTexCoord;
|
||||
}
|
||||
128
FLARDATA/Shader/brdf.fp
Normal file
128
FLARDATA/Shader/brdf.fp
Normal file
@@ -0,0 +1,128 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Code based on https://learnopengl.com/PBR/IBL/Specular-IBL
|
||||
|
||||
|
||||
#version 330
|
||||
in vec2 TexCoords;
|
||||
|
||||
const float PI = 3.14159265359;
|
||||
// ----------------------------------------------------------------------------
|
||||
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
|
||||
// efficient VanDerCorpus calculation.
|
||||
float RadicalInverse_VdC(uint bits)
|
||||
{
|
||||
bits = (bits << 16u) | (bits >> 16u);
|
||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
vec2 Hammersley(uint i, uint N)
|
||||
{
|
||||
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughnessSquared)
|
||||
{
|
||||
//float a = roughness*roughness;
|
||||
float a = roughnessSquared;
|
||||
|
||||
float phi = 2.0 * PI * Xi.x;
|
||||
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
|
||||
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
|
||||
|
||||
// from spherical coordinates to cartesian coordinates - halfway vector
|
||||
vec3 H;
|
||||
H.x = cos(phi) * sinTheta;
|
||||
H.y = sin(phi) * sinTheta;
|
||||
H.z = cosTheta;
|
||||
|
||||
// from tangent-space H vector to world-space sample vector
|
||||
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 tangent = normalize(cross(up, N));
|
||||
vec3 bitangent = cross(N, tangent);
|
||||
|
||||
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
||||
return normalize(sampleVec);
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||
{
|
||||
// note that we use a different k for IBL
|
||||
float a = roughness;
|
||||
float k = (a * a) / 2.0;
|
||||
|
||||
float nom = NdotV;
|
||||
float denom = NdotV * (1.0 - k) + k + 0.00001; // 0.00001 to prevent divide by zero.
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
float GeometrySmith(float NdotV, float NdotL, float roughness)
|
||||
{
|
||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||
|
||||
return ggx1 * ggx2;
|
||||
}
|
||||
//"PBR Diffuse Lighting for GGX+Smith Microsurfaces", Earl Hammon, Jr.
|
||||
float GeometrySmithG2Hammon(float NdotV, float NdotL, float roughnessSquared)
|
||||
{
|
||||
float nom = 2*NdotL*NdotV;
|
||||
float denom = mix(2*NdotL*NdotV,NdotL+NdotV,roughnessSquared) + 0.00001; // 0.00001 to prevent divide by zero.
|
||||
return nom/denom;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
vec2 IntegrateBRDF(float NdotV, float roughness)
|
||||
{
|
||||
vec3 V;
|
||||
V.x = sqrt(1.0 - NdotV*NdotV);
|
||||
V.y = 0.0;
|
||||
V.z = NdotV;
|
||||
|
||||
float A = 0.0;
|
||||
float B = 0.0;
|
||||
|
||||
vec3 N = vec3(0.0, 0.0, 1.0);
|
||||
|
||||
float roughnessSquared = roughness*roughness;
|
||||
|
||||
const uint SAMPLE_COUNT = 1024u;
|
||||
for(uint i = 0u; i < SAMPLE_COUNT; ++i)
|
||||
{
|
||||
// generates a sample vector that's biased towards the
|
||||
// preferred alignment direction (importance sampling).
|
||||
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
|
||||
vec3 H = ImportanceSampleGGX(Xi, N, roughnessSquared);
|
||||
vec3 L = normalize(2.0 * dot(V, H) * H - V);
|
||||
|
||||
float NdotL = max(L.z, 0.0);
|
||||
|
||||
if(NdotL > 0.0)
|
||||
{
|
||||
float NdotH = max(H.z, 0.0);
|
||||
float VdotH = max(dot(V, H), 0.0);
|
||||
//float G = GeometrySmith(NdotV, NdotL, roughness);
|
||||
float G = GeometrySmithG2Hammon(NdotV, NdotL, roughnessSquared);
|
||||
float G_Vis = (G * VdotH) / (NdotH * NdotV);
|
||||
float Fc = pow(1.0 - VdotH, 5.0);
|
||||
|
||||
A += (1.0 - Fc) * G_Vis;
|
||||
B += Fc * G_Vis;
|
||||
}
|
||||
}
|
||||
A /= float(SAMPLE_COUNT);
|
||||
B /= float(SAMPLE_COUNT);
|
||||
return vec2(A, B);
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
void main()
|
||||
{
|
||||
vec2 integratedBRDF = IntegrateBRDF(TexCoords.x, TexCoords.y);
|
||||
gl_FragColor.rg = integratedBRDF;
|
||||
}
|
||||
17
FLARDATA/Shader/brdf.vs
Normal file
17
FLARDATA/Shader/brdf.vs
Normal file
@@ -0,0 +1,17 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Code based on https://learnopengl.com/PBR/IBL/Specular-IBL
|
||||
|
||||
|
||||
#version 330
|
||||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec2 aTexCoords;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
void main()
|
||||
{
|
||||
TexCoords = aTexCoords;
|
||||
gl_Position = vec4(aPos, 1.0);
|
||||
}
|
||||
18
FLARDATA/Shader/cubemap.vs
Normal file
18
FLARDATA/Shader/cubemap.vs
Normal file
@@ -0,0 +1,18 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Code based on https://learnopengl.com/PBR/IBL/Specular-IBL
|
||||
|
||||
#version 330
|
||||
layout (location = 0) in vec3 aPos;
|
||||
|
||||
out vec3 WorldPos;
|
||||
|
||||
uniform mat4 projectionMat;
|
||||
uniform mat4 viewMat;
|
||||
|
||||
void main()
|
||||
{
|
||||
WorldPos = aPos;
|
||||
gl_Position = projectionMat * viewMat * vec4(WorldPos, 1.0);
|
||||
}
|
||||
20
FLARDATA/Shader/depthOnly.fp
Normal file
20
FLARDATA/Shader/depthOnly.fp
Normal file
@@ -0,0 +1,20 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Depth only shader for FLAR by Schmackbolzen
|
||||
|
||||
#version 330
|
||||
|
||||
uniform sampler2D texture;
|
||||
uniform float alphaTestValue;
|
||||
in vec2 outTexCoords;
|
||||
|
||||
void main()
|
||||
{
|
||||
if (alphaTestValue > 0)
|
||||
{
|
||||
if (texture2D(texture, outTexCoords).a < alphaTestValue)
|
||||
discard;
|
||||
}
|
||||
gl_FragColor = vec4(1,0,0,1);
|
||||
}
|
||||
30
FLARDATA/Shader/depthOnly.gs
Normal file
30
FLARDATA/Shader/depthOnly.gs
Normal file
@@ -0,0 +1,30 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Code based on "Parallel-Split Shadow Maps on Programmable GPUs" GPU Gems 3 (2005)
|
||||
|
||||
#version 330
|
||||
const int g_iNumSplits = $NUM_SPLITS;
|
||||
|
||||
layout (triangles) in;
|
||||
layout (triangle_strip, max_vertices = 3) out;
|
||||
|
||||
flat in int splitIndex[];
|
||||
|
||||
in vec2 inTexCoords[];
|
||||
uniform mat4 mvpMat[g_iNumSplits];
|
||||
|
||||
out vec2 outTexCoords;
|
||||
|
||||
void main()
|
||||
{
|
||||
for(int iVertex = 0; iVertex < 3; iVertex++)
|
||||
{
|
||||
int iSplit = splitIndex[iVertex];
|
||||
gl_Layer = iSplit;
|
||||
gl_Position = mvpMat[iSplit]*gl_in[iVertex].gl_Position;
|
||||
outTexCoords = inTexCoords[iVertex];
|
||||
EmitVertex();
|
||||
}
|
||||
EndPrimitive();
|
||||
}
|
||||
46
FLARDATA/Shader/depthOnly.vs
Normal file
46
FLARDATA/Shader/depthOnly.vs
Normal file
@@ -0,0 +1,46 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Code based on "Parallel-Split Shadow Maps on Programmable GPUs" GPU Gems 3 (2005)
|
||||
#version 330
|
||||
|
||||
layout (location = 0) in vec4 inPosition;
|
||||
layout (location = 4) in vec2 inTexCoord0;
|
||||
layout (location = 6) in mat4 inMVPMatInstanced;
|
||||
layout (location = 10) in int inSplitIndexInstanced;
|
||||
|
||||
out vec2 inTexCoords;
|
||||
flat out int splitIndex;
|
||||
|
||||
const int g_iNumSplits = $NUM_SPLITS;
|
||||
|
||||
uniform mat4 worldMat;
|
||||
uniform bool isInstanced;
|
||||
uniform bool isInstancedSplits;
|
||||
uniform float alphaTestValue;
|
||||
uniform int firstSplit;
|
||||
|
||||
void main(){
|
||||
mat4 mvp;
|
||||
|
||||
if(!isInstanced)
|
||||
mvp=worldMat;
|
||||
else
|
||||
{
|
||||
mvp=inMVPMatInstanced;
|
||||
}
|
||||
|
||||
if(!isInstancedSplits)
|
||||
{
|
||||
splitIndex = firstSplit + gl_InstanceID;
|
||||
}
|
||||
else
|
||||
{
|
||||
splitIndex = inSplitIndexInstanced;
|
||||
}
|
||||
|
||||
gl_Position = mvp * inPosition;
|
||||
if (alphaTestValue > 0)
|
||||
inTexCoords = inTexCoord0.st;
|
||||
}
|
||||
|
||||
401
FLARDATA/Shader/fixedFunction.fp
Normal file
401
FLARDATA/Shader/fixedFunction.fp
Normal file
@@ -0,0 +1,401 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Fixed function shader for FLAR by Schmackbolzen
|
||||
|
||||
#version 330
|
||||
#define TEXTURESTAGE_COUNT 2
|
||||
#include "ColorConversion.inc"
|
||||
|
||||
struct Light{
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec4 position;
|
||||
vec3 spotDirection;
|
||||
float spotExponent;
|
||||
float spotCosPhi;
|
||||
float spotCosTheta;
|
||||
float constantAttenuation;
|
||||
float linearAttenuation;
|
||||
float quadraticAttenuation;
|
||||
float range;
|
||||
};
|
||||
|
||||
struct glFogParameters
|
||||
{
|
||||
vec3 color;
|
||||
float density;
|
||||
float start;
|
||||
float end;
|
||||
};
|
||||
|
||||
|
||||
uniform Light glLightSource[8];
|
||||
uniform glFogParameters glFog;
|
||||
uniform sampler2D textures[TEXTURESTAGE_COUNT];
|
||||
uniform samplerCube cubemap;
|
||||
uniform int colorOp[TEXTURESTAGE_COUNT];
|
||||
uniform int alphaOp[TEXTURESTAGE_COUNT];
|
||||
uniform int colorArg1[TEXTURESTAGE_COUNT];
|
||||
uniform int colorArg2[TEXTURESTAGE_COUNT];
|
||||
uniform int alphaArg1[TEXTURESTAGE_COUNT];
|
||||
uniform int alphaArg2[TEXTURESTAGE_COUNT];
|
||||
uniform bool textureBound[TEXTURESTAGE_COUNT];
|
||||
uniform vec3 ambientColor;
|
||||
uniform vec3 matAmbientColor;
|
||||
uniform vec4 matDiffuseColor;
|
||||
uniform vec3 matEmissiveColor;
|
||||
uniform vec4 matSpecularColor;
|
||||
uniform float alphaTestValue;
|
||||
uniform int alphaTestCompareMethod;
|
||||
uniform int lightCount;
|
||||
uniform int texture1Index;
|
||||
uniform int fogMode;
|
||||
|
||||
uniform bool enableVertexColor;
|
||||
uniform bool vertexColorAvailable;
|
||||
uniform bool specularVertexColorAvailable;
|
||||
uniform bool enableLighting;
|
||||
uniform bool enableAlphaTest;
|
||||
uniform bool enableCubemap;
|
||||
uniform bool enableRHWCoordinates;
|
||||
uniform bool enableAccurateSRGB;
|
||||
|
||||
in vec3 N;
|
||||
in vec3 v;
|
||||
in float RHWdepth;
|
||||
in vec2 texCoords[2];
|
||||
in vec4 vertexColor;
|
||||
in vec4 vertexColorSecondary;
|
||||
in float fogEnd;
|
||||
in float fogScale;
|
||||
|
||||
#define D3DTA_DIFFUSE 0x00000000 // select diffuse color (read only)
|
||||
#define D3DTA_CURRENT 0x00000001 // select stage destination register (read/write)
|
||||
#define D3DTA_TEXTURE 0x00000002 // select texture color (read only)
|
||||
#define D3DTA_TFACTOR 0x00000003 // select D3DRS_TEXTUREFACTOR (read only)
|
||||
#define D3DTA_SPECULAR 0x00000004 // select specular color (read only)
|
||||
#define D3DTA_TEMP 0x00000005 // select temporary register color (read/write)
|
||||
#define D3DTA_COMPLEMENT 0x00000010 // take 1.0 x (read modifier)
|
||||
#define D3DTA_ALPHAREPLICATE 0x00000020 // replicate alpha to color components (read modifier)
|
||||
|
||||
#define D3DTOP_DISABLE 1 // disables stage
|
||||
#define D3DTOP_SELECTARG1 2 // the default
|
||||
#define D3DTOP_SELECTARG2 3
|
||||
|
||||
// Modulate
|
||||
#define D3DTOP_MODULATE 4 // multiply args together
|
||||
#define D3DTOP_MODULATE2X 5 // multiply and << 1 bit
|
||||
#define D3DTOP_MODULATE4X 6 // multiply and << 2 bits
|
||||
|
||||
// Add
|
||||
#define D3DTOP_ADD 7 // add arguments together
|
||||
#define D3DTOP_ADDSIGNED 8 // add with -0.5 bias
|
||||
#define D3DTOP_ADDSIGNED2X 9 // as above but left << 1 bit
|
||||
|
||||
vec3 ToLinear(vec3 inColor)
|
||||
{
|
||||
if (enableAccurateSRGB)
|
||||
return ToLinearAccurate(inColor);
|
||||
else
|
||||
return ToLinearFast(inColor);
|
||||
}
|
||||
|
||||
vec3 ToGammaCorrected(vec3 inColor)
|
||||
{
|
||||
if (enableAccurateSRGB)
|
||||
return ToGammaCorrectedAccurate(inColor);
|
||||
else
|
||||
return ToGammaCorrectedFast(inColor);
|
||||
}
|
||||
|
||||
vec4 GetColorForStage(const int stage, int colorArg, int alphaArg, vec4 previousColor, vec4 gouradDiffuseColor, vec4 specularColor, vec2 texCoords, vec3 cubeMapTexCoords)
|
||||
{
|
||||
vec4 color;
|
||||
vec4 textureColor;
|
||||
if(colorArg == D3DTA_TEXTURE || alphaArg == D3DTA_TEXTURE)
|
||||
if(textureBound[stage])
|
||||
//Use if because some glsl compilers can not propagate the constant stage even though it has a constant value
|
||||
//when the function gets called (0 or 1) and complain about missing glsl compliance for texture lookup (no constant index)
|
||||
if (stage==0)
|
||||
textureColor=texture2D(textures[0],texCoords);
|
||||
else
|
||||
if (!enableCubemap)
|
||||
textureColor=texture2D(textures[1],texCoords);
|
||||
else
|
||||
textureColor=texture(cubemap,cubeMapTexCoords);
|
||||
else
|
||||
textureColor=vec4(1);
|
||||
|
||||
//textureColor.rgb=ToLinear(textureColor.rgb);
|
||||
|
||||
if(colorArg == D3DTA_DIFFUSE)
|
||||
color.rgb=gouradDiffuseColor.rgb;
|
||||
else if(colorArg == D3DTA_CURRENT)
|
||||
color.rgb=previousColor.rgb;
|
||||
else if(colorArg == D3DTA_TEXTURE)
|
||||
color.rgb=textureColor.rgb;
|
||||
else if(colorArg == D3DTA_SPECULAR)
|
||||
color.rgb =specularColor.rgb;
|
||||
else
|
||||
color=vec4(1,0,0,1);
|
||||
|
||||
if(alphaArg == D3DTA_DIFFUSE)
|
||||
color.a=gouradDiffuseColor.a;
|
||||
else if(alphaArg == D3DTA_CURRENT)
|
||||
color.a=previousColor.a;
|
||||
else if(alphaArg == D3DTA_TEXTURE)
|
||||
color.a=textureColor.a;
|
||||
else if(alphaArg == D3DTA_SPECULAR)
|
||||
color.a =specularColor.a;
|
||||
else
|
||||
color=vec4(1,0,0,1);
|
||||
return color;
|
||||
}
|
||||
|
||||
vec4 ApplyFunctionForStage(const int stage, vec4 previousColor, vec4 gouradDiffuseColor, vec4 specularColor, vec2 texCoords, vec3 cubeMapTexCoords)
|
||||
{
|
||||
vec4 color1=GetColorForStage(stage,colorArg1[stage],alphaArg1[stage], previousColor, gouradDiffuseColor, specularColor, texCoords, cubeMapTexCoords);
|
||||
vec4 color2=GetColorForStage(stage,colorArg2[stage],alphaArg2[stage], previousColor, gouradDiffuseColor, specularColor, texCoords, cubeMapTexCoords);
|
||||
|
||||
if (colorOp[stage]==D3DTOP_SELECTARG2)
|
||||
{
|
||||
color1.rgb = color2.rgb;
|
||||
}
|
||||
else if (colorOp[stage]==D3DTOP_MODULATE)
|
||||
{
|
||||
color1.rgb*=color2.rgb;
|
||||
}
|
||||
else if (colorOp[stage]==D3DTOP_MODULATE2X)
|
||||
{
|
||||
color1.rgb=color1.rgb*color2.rgb*4.6; //2^2.2 since rendering is gamma correct
|
||||
}
|
||||
else if (colorOp[stage]==D3DTOP_MODULATE4X)
|
||||
{
|
||||
color1.rgb=color1.rgb*color2.rgb*21.11; //4^2.2 since rendering is gamma correct
|
||||
}
|
||||
else if (colorOp[stage]==D3DTOP_ADD)
|
||||
{
|
||||
color1.rgb=color1.rgb+color2.rgb;
|
||||
}
|
||||
else if (colorOp[stage]==D3DTOP_ADDSIGNED)
|
||||
{
|
||||
color1.rgb=color1.rgb+color2.rgb-0.5;
|
||||
}
|
||||
else if (colorOp[stage]==D3DTOP_ADDSIGNED2X)
|
||||
{
|
||||
color1.rgb=(color1.rgb+color2.rgb-0.5)*4.6; //2^2.2 since rendering is gamma correct
|
||||
}
|
||||
|
||||
if (alphaOp[stage]==D3DTOP_SELECTARG2)
|
||||
{
|
||||
color1.a = color2.a;
|
||||
}
|
||||
else if (alphaOp[stage]==D3DTOP_MODULATE)
|
||||
{
|
||||
color1.a*=color2.a;
|
||||
}
|
||||
else if (alphaOp[stage]==D3DTOP_MODULATE2X)
|
||||
{
|
||||
color1.a=(color1.a*color2.a)*4.6; //2^2.2 since rendering is gamma correct
|
||||
}
|
||||
else if (alphaOp[stage]==D3DTOP_MODULATE4X)
|
||||
{
|
||||
color1.a=(color1.a*color2.a)*21.11; //4^2.2 since rendering is gamma correct
|
||||
}
|
||||
else if (alphaOp[stage]==D3DTOP_ADD)
|
||||
{
|
||||
color1.a=(color1.a+color2.a);
|
||||
}
|
||||
else if (alphaOp[stage]==D3DTOP_ADDSIGNED)
|
||||
{
|
||||
color1.a=color1.a+color2.a-0.5;
|
||||
}
|
||||
else if (alphaOp[stage]==D3DTOP_ADDSIGNED2X)
|
||||
{
|
||||
color1.a=(color1.a+color2.a-0.5)*4.6; //2^2.2 since rendering is gamma correct
|
||||
}
|
||||
color1.a=pow(color1.a,1.2);
|
||||
|
||||
return color1;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 gouradDiffuseColor;
|
||||
vec4 specularColor;
|
||||
vec3 vertexAmbientColor;
|
||||
|
||||
if (enableLighting)
|
||||
{
|
||||
if(enableVertexColor)
|
||||
{
|
||||
|
||||
float alpha = vertexColorAvailable ? vertexColor.a : matDiffuseColor.a;
|
||||
if (specularVertexColorAvailable)
|
||||
{
|
||||
vertexAmbientColor=ToLinear(vertexColorSecondary.rgb);
|
||||
gouradDiffuseColor=vec4(ambientColor*vertexAmbientColor,alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexAmbientColor=matAmbientColor.rgb;
|
||||
gouradDiffuseColor=vec4(ambientColor*vertexAmbientColor,alpha);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexAmbientColor=matAmbientColor.rgb;
|
||||
gouradDiffuseColor=vec4(ambientColor*vertexAmbientColor,matDiffuseColor.a);
|
||||
}
|
||||
//FL never has specular lighting enabled
|
||||
specularColor=vec4(0,0,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(vertexColorAvailable)
|
||||
{
|
||||
//gouradDiffuseColor=vec4(ToLinear(vertexColor.rgb),vertexColor.a);
|
||||
//TODO: Weird bug with MSAA and float16 render target
|
||||
vec4 vertexColorAboveZero=max(vertexColor,0);
|
||||
gouradDiffuseColor=vec4(ToLinear(vertexColorAboveZero.rgb),vertexColorAboveZero.a);
|
||||
}
|
||||
else
|
||||
gouradDiffuseColor=vec4(1,1,1,1);
|
||||
|
||||
if(specularVertexColorAvailable)
|
||||
specularColor=vec4(ToLinear(vertexColorSecondary.rgb),vertexColor.a);
|
||||
else
|
||||
specularColor=vec4(0,0,0,0);
|
||||
}
|
||||
|
||||
vec3 normal=normalize(N);
|
||||
if (enableLighting)
|
||||
{
|
||||
gouradDiffuseColor.rgb+=matEmissiveColor;
|
||||
vec3 vertexDiffuseColor=vertexColorAvailable&&enableVertexColor ? ToLinear(vertexColor.rgb): matDiffuseColor.rgb;
|
||||
|
||||
for (int index = 0; index < lightCount; index++)
|
||||
{
|
||||
|
||||
vec3 lightDir;
|
||||
float attenFactor;
|
||||
// attenuation and light direction
|
||||
if(glLightSource[index].spotCosTheta != -1.)
|
||||
{
|
||||
lightDir = normalize(glLightSource[index].position.xyz - v);
|
||||
|
||||
float angle = max(dot(normalize(glLightSource[index].spotDirection), -lightDir),0);
|
||||
|
||||
if (angle > glLightSource[index].spotCosPhi)
|
||||
{
|
||||
float spotAtten;
|
||||
if (angle < glLightSource[index].spotCosTheta)
|
||||
spotAtten = (angle-glLightSource[index].spotCosPhi)/(glLightSource[index].spotCosTheta-glLightSource[index].spotCosPhi);
|
||||
else
|
||||
spotAtten = 1;
|
||||
|
||||
if(glLightSource[index].spotExponent != 1.0)
|
||||
spotAtten = pow(spotAtten, glLightSource[index].spotExponent);
|
||||
|
||||
float dist = distance(glLightSource[index].position.xyz, v);
|
||||
attenFactor = spotAtten * min(1.0/ (glLightSource[index].constantAttenuation +
|
||||
glLightSource[index].linearAttenuation * dist +
|
||||
glLightSource[index].quadraticAttenuation * dist * dist),1);
|
||||
}
|
||||
else
|
||||
attenFactor = 0.;
|
||||
}
|
||||
else if (glLightSource[index].position.w != 0.0)
|
||||
{
|
||||
// positional light source
|
||||
float dist = distance(glLightSource[index].position.xyz, v);
|
||||
if (dist <= glLightSource[index].range )
|
||||
{
|
||||
attenFactor = min(1.0/( glLightSource[index].constantAttenuation +
|
||||
glLightSource[index].linearAttenuation * dist +
|
||||
glLightSource[index].quadraticAttenuation * dist * dist ),1);
|
||||
lightDir = normalize(glLightSource[index].position.xyz - v);
|
||||
}
|
||||
else
|
||||
attenFactor = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
attenFactor = 1;
|
||||
lightDir = normalize(glLightSource[index].position.xyz);
|
||||
}
|
||||
if(attenFactor > 0)
|
||||
{
|
||||
float intensity = max(dot(normal,lightDir),0.0);
|
||||
|
||||
vec3 lightColorAmbient = glLightSource[index].ambient.rgb*vertexAmbientColor;
|
||||
vec3 lightColorDiffuse = glLightSource[index].diffuse.rgb*vertexDiffuseColor*intensity;
|
||||
gouradDiffuseColor.rgb += (lightColorAmbient + lightColorDiffuse)*attenFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vec4 finalColor=gouradDiffuseColor;
|
||||
if (colorOp[0]!=D3DTOP_DISABLE)
|
||||
{
|
||||
vec3 cubeMapTexCoords;
|
||||
finalColor=ApplyFunctionForStage(0,finalColor,gouradDiffuseColor,specularColor,texCoords[0], cubeMapTexCoords);
|
||||
|
||||
if (colorOp[1]!=D3DTOP_DISABLE)
|
||||
{
|
||||
|
||||
if(enableCubemap)
|
||||
cubeMapTexCoords=reflect(v,normal);
|
||||
finalColor=ApplyFunctionForStage(1,finalColor,gouradDiffuseColor,specularColor,texCoords[1], cubeMapTexCoords);
|
||||
}
|
||||
}
|
||||
else
|
||||
finalColor=gouradDiffuseColor;
|
||||
|
||||
if (enableAlphaTest)
|
||||
if(alphaTestCompareMethod==5)
|
||||
{
|
||||
if( finalColor.a <= alphaTestValue)
|
||||
discard;
|
||||
}
|
||||
else if(alphaTestCompareMethod==2)
|
||||
{
|
||||
if( finalColor.a > alphaTestValue)
|
||||
discard;
|
||||
}
|
||||
else
|
||||
finalColor =vec4(1,0,0,1);
|
||||
|
||||
if (fogMode > 0)
|
||||
{
|
||||
float z;
|
||||
if(enableRHWCoordinates)
|
||||
z = RHWdepth;
|
||||
else
|
||||
//Radial fog
|
||||
z = length(v);
|
||||
|
||||
const float LOG2E = 1.442695;
|
||||
float fogFactor;
|
||||
if (fogMode == 3)
|
||||
{
|
||||
fogFactor = (fogEnd - z) * fogScale;
|
||||
}
|
||||
else if (fogMode == 1)
|
||||
{
|
||||
fogFactor =exp(-glFog.density * z);
|
||||
}
|
||||
else if (fogMode == 2)
|
||||
{
|
||||
fogFactor = exp2(-glFog.density * glFog.density * z * z * LOG2E);
|
||||
}
|
||||
else
|
||||
fogFactor = 1;
|
||||
|
||||
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||
finalColor.rgb = mix(glFog.color.rgb,finalColor.rgb, fogFactor);
|
||||
}
|
||||
gl_FragColor = vec4(ToGammaCorrected(finalColor.rgb), finalColor.a);
|
||||
//gl_FragColor = finalColor;
|
||||
}
|
||||
109
FLARDATA/Shader/fixedFunction.vs
Normal file
109
FLARDATA/Shader/fixedFunction.vs
Normal file
@@ -0,0 +1,109 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Fixed function shader for FLAR by Schmackbolzen
|
||||
|
||||
#version 330
|
||||
out vec2 texCoords[2];
|
||||
out vec3 N;
|
||||
out vec3 v;
|
||||
out float RHWdepth;
|
||||
out vec4 vertexColor;
|
||||
out vec4 vertexColorSecondary;
|
||||
out float fogEnd;
|
||||
out float fogScale;
|
||||
|
||||
struct glFogParameters
|
||||
{
|
||||
vec3 color;
|
||||
float density;
|
||||
float start;
|
||||
float end;
|
||||
};
|
||||
|
||||
uniform glFogParameters glFog;
|
||||
uniform bool enableRHWCoordinates;
|
||||
uniform mat4 modelViewMat;
|
||||
uniform mat4 projectionMat;
|
||||
uniform mat3 normalMat;
|
||||
uniform vec2 projCorrection;
|
||||
uniform mat4 textureMatrix[2];
|
||||
uniform bool isInstanced;
|
||||
uniform bool isInstancedTransparent;
|
||||
uniform bool isInstancedFog;
|
||||
uniform bool enableTextureTransform0;
|
||||
uniform bool enableTextureTransform1;
|
||||
uniform int texture1Index;
|
||||
|
||||
layout (location = 0) in vec4 inPosition;
|
||||
layout (location = 1) in vec3 inNormal;
|
||||
layout (location = 2) in vec4 inColor;
|
||||
layout (location = 3) in vec4 inSecondColor;
|
||||
layout (location = 4) in vec4 inTexCoord0;
|
||||
layout (location = 6) in mat4 inModelViewMatInstanced;
|
||||
layout (location = 10) in float inAlphaValue;
|
||||
layout (location = 11) in vec2 inFogStartEndInstanced;
|
||||
|
||||
void main()
|
||||
{
|
||||
mat4 mv;
|
||||
if(!isInstanced)
|
||||
mv=modelViewMat;
|
||||
else
|
||||
mv=inModelViewMatInstanced;
|
||||
|
||||
vertexColor.rgba = (inColor).bgra;
|
||||
vertexColorSecondary.rgba=inSecondColor.bgra;
|
||||
|
||||
if(isInstancedTransparent)
|
||||
{
|
||||
vertexColor.a = inAlphaValue;
|
||||
}
|
||||
|
||||
if(!isInstancedFog)
|
||||
{
|
||||
fogEnd = glFog.end;
|
||||
fogScale = 1.0f / (glFog.end - glFog.start);
|
||||
}
|
||||
else
|
||||
{
|
||||
fogEnd = inFogStartEndInstanced.y;
|
||||
fogScale = 1.0f / (inFogStartEndInstanced.y - inFogStartEndInstanced.x);
|
||||
}
|
||||
|
||||
v = vec3(mv * inPosition);
|
||||
N = normalize(mat3(mv) * inNormal);
|
||||
|
||||
if (!enableRHWCoordinates)
|
||||
gl_Position = projectionMat * mv * inPosition;
|
||||
else
|
||||
{
|
||||
gl_Position = vec4((inPosition.x+63.0f / 128.0f)*projCorrection[0]-1,-(inPosition.y+63.0f / 128.0f)*projCorrection[1]+1,inPosition.z*2-1,1);
|
||||
RHWdepth = inPosition.z/inPosition.w;
|
||||
}
|
||||
|
||||
if(enableTextureTransform0)
|
||||
{
|
||||
vec4 texCoords0=vec4(inTexCoord0.xy,0,1);
|
||||
texCoords[0] = (textureMatrix[0]*texCoords0).xy;
|
||||
}
|
||||
else
|
||||
texCoords[0] = inTexCoord0.xy;
|
||||
|
||||
if (texture1Index == 0)
|
||||
if(enableTextureTransform1)
|
||||
{
|
||||
vec4 texCoords0=vec4(inTexCoord0.xy,0,1);
|
||||
texCoords[1] = (textureMatrix[1]*texCoords0).xy;
|
||||
}
|
||||
else
|
||||
texCoords[1] = inTexCoord0.xy;
|
||||
else if (texture1Index == 1)
|
||||
if(enableTextureTransform1)
|
||||
{
|
||||
vec4 texCoords1=vec4(inTexCoord0.zw,0,1);
|
||||
texCoords[1] = (textureMatrix[1]*texCoords1).xy;
|
||||
}
|
||||
else
|
||||
texCoords[1] = inTexCoord0.zw;
|
||||
}
|
||||
25
FLARDATA/Shader/histogramBin.fp
Normal file
25
FLARDATA/Shader/histogramBin.fp
Normal file
@@ -0,0 +1,25 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//
|
||||
//Simple histogram shader for FLAR by Schmackbolzen
|
||||
|
||||
#version 330
|
||||
#include "ColorConversion.inc"
|
||||
#define NUM_LIMITS $NUM_LIMITS
|
||||
in vec2 TexCoords;
|
||||
|
||||
uniform sampler2D scene;
|
||||
uniform vec2 limits[NUM_LIMITS];
|
||||
uniform int index;
|
||||
|
||||
void main()
|
||||
{
|
||||
float luma = clamp(ToLuma(texture2D(scene, TexCoords).rgb),limits[0].x,limits[NUM_LIMITS-1].x);
|
||||
vec2 currentLimits=limits[index];
|
||||
bool withinLimits;
|
||||
withinLimits = (luma >= currentLimits.x) && (luma < currentLimits.y);
|
||||
if (!withinLimits)
|
||||
discard;
|
||||
gl_FragDepth= 0;
|
||||
}
|
||||
722
FLARDATA/Shader/lighting.fp
Normal file
722
FLARDATA/Shader/lighting.fp
Normal file
@@ -0,0 +1,722 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//PBR lighting shader for FLAR by Schmackbolzen
|
||||
//Sources are either mentioned in the comments below,
|
||||
//from https://learnopengl.com/PBR/Lighting or https://learnopengl.com/PBR/IBL/Specular-IBL
|
||||
//or "Parallel-Split Shadow Maps on Programmable GPUs" GPU Gems 3 (2005)
|
||||
|
||||
#version 330
|
||||
#include "ColorConversion.inc"
|
||||
#define MAX_SHADOWS $MAX_SHADOWS
|
||||
#define NUM_SPLITS $NUM_SPLITS
|
||||
#define USE_PCF $USE_PCF
|
||||
#define USE_HQ_DIFFUSE $USE_HQ_DIFFUSE
|
||||
#define USE_PARALLAX_MAPS $USE_PARALLAX_MAPS
|
||||
#define USE_CLUSTERED_SHADING $USE_CLUSTERED_SHADING
|
||||
|
||||
|
||||
//#define SIMPLE_KD
|
||||
#define IBL_MULTIPLE_SCATTERING
|
||||
|
||||
#if USE_CLUSTERED_SHADING == 1
|
||||
#define NUM_POSSIBLE_LIGHTS $NUM_POSSIBLE_LIGHTS
|
||||
#define LIGHT_GRID_TILE_DIM_X $LIGHT_GRID_TILE_DIM_X
|
||||
#define LIGHT_GRID_TILE_DIM_Y $LIGHT_GRID_TILE_DIM_Y
|
||||
#define LIGHT_GRID_MAX_DIM_X $LIGHT_GRID_MAX_DIM_X
|
||||
#define LIGHT_GRID_MAX_DIM_Y $LIGHT_GRID_MAX_DIM_Y
|
||||
#endif
|
||||
|
||||
const float PBR_FACTOR = 2;
|
||||
const float PBR_FACTOR_ENV = 1.5;
|
||||
|
||||
in vec3 eyeVec;
|
||||
in vec3 v,vWorld,worldNormal;
|
||||
in vec3 N;
|
||||
in mat3 tbnMatrix,tbnMatrixObj;
|
||||
in vec4 shadowCoord[MAX_SHADOWS*NUM_SPLITS];
|
||||
in vec4 texCoords;
|
||||
in mat3 worldRotMat;
|
||||
in float alphaValue;
|
||||
|
||||
in float fogEnd;
|
||||
in float fogScale;
|
||||
|
||||
struct Light{
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec4 position;
|
||||
vec3 spotDirection;
|
||||
float spotExponent;
|
||||
float spotCosPhi;
|
||||
float spotCosTheta;
|
||||
float constantAttenuation;
|
||||
float linearAttenuation;
|
||||
float quadraticAttenuation;
|
||||
};
|
||||
|
||||
struct glFogParameters
|
||||
{
|
||||
vec3 color;
|
||||
float density;
|
||||
float start;
|
||||
float end;
|
||||
};
|
||||
|
||||
#if USE_CLUSTERED_SHADING == 1
|
||||
//Has to be 16 byte aligned (otherwise it will be padded)
|
||||
struct ClusteredLight{
|
||||
vec4 position;
|
||||
vec4 diffuse;
|
||||
};
|
||||
|
||||
layout (std140) uniform LightSourceClustered
|
||||
{
|
||||
ClusteredLight clusteredLights[NUM_POSSIBLE_LIGHTS];
|
||||
};
|
||||
|
||||
uniform isamplerBuffer clusterLightIndexListsTex;
|
||||
uniform usamplerBuffer clusterGridTex;
|
||||
#endif
|
||||
|
||||
uniform glFogParameters glFog;
|
||||
uniform Light glLightSource[8];
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D tex2;
|
||||
uniform sampler2D heightMap;
|
||||
uniform sampler2D normalMap;
|
||||
uniform sampler2D roughnessMap;
|
||||
uniform sampler2D metalnessMap;
|
||||
uniform sampler2D reflectionMap;
|
||||
uniform sampler2D brdfLUT;
|
||||
uniform sampler2DArrayShadow shadowMap[MAX_SHADOWS];
|
||||
uniform float splitPlanes[NUM_SPLITS];
|
||||
|
||||
uniform samplerCube envMap;
|
||||
uniform samplerCube irradianceMap;
|
||||
uniform vec2 texture1Size;
|
||||
uniform vec2 textureShadowSize;
|
||||
uniform int lightCount;
|
||||
uniform int shadowCount;
|
||||
uniform int tex2Mode;
|
||||
uniform int fogMode;
|
||||
uniform float metalnessConst;
|
||||
uniform float roughnessConst;
|
||||
uniform float roughnessTextureBias;
|
||||
|
||||
uniform mat4 invWorldView;
|
||||
uniform vec3 camPos;
|
||||
uniform vec3 ambientColor;
|
||||
uniform vec3 matAmbientColor;
|
||||
uniform vec3 matDiffuseColor;
|
||||
uniform vec3 matEmissiveColor;
|
||||
uniform int alphaTestCompareMethod;
|
||||
uniform float alphaTestValue;
|
||||
|
||||
uniform bool enableNormalMaps;
|
||||
uniform bool enableParallaxMaps;
|
||||
uniform bool enableFirstTexture;
|
||||
uniform bool enableSecondTexture;
|
||||
uniform bool enableFog;
|
||||
uniform bool enableEnvMap;
|
||||
uniform bool enableTex2Modulate2X;
|
||||
uniform bool enableRoughnessMap;
|
||||
uniform bool enableMetalnessMap;
|
||||
uniform bool enableAlphaTest;
|
||||
#if USE_CLUSTERED_SHADING == 1
|
||||
uniform bool enableClusteredShading;
|
||||
uniform float recNear; /**< 1.0f / g_near */
|
||||
uniform float recLogSD1; /**< 1.0f / logf(sD + 1.0f), used to compute cluster index. */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
float HEIGHT_SCALE = 0.01;
|
||||
|
||||
const float PI = 3.141592654;
|
||||
|
||||
out vec4 diffuseColorOut;
|
||||
|
||||
|
||||
float ShadowCalculation(const float bias, const int shadowMapIndex, const int lightIndex, const sampler2DArrayShadow shadowSampler)
|
||||
{
|
||||
vec4 fragPosLightSpace = shadowCoord[lightIndex*NUM_SPLITS+shadowMapIndex];
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
#if USE_PCF == 1
|
||||
float currentDepth = clamp(projCoords.z,0,1);
|
||||
|
||||
|
||||
// Check whether current frag pos is in shadow
|
||||
//if(projCoords.z <= 1.0)
|
||||
{
|
||||
float shadow = 0.0;
|
||||
vec2 texelSize = 1.0 / vec2(textureShadowSize);
|
||||
for(int x = -1; x <= 1; ++x)
|
||||
{
|
||||
for(int y = -1; y <= 1; ++y)
|
||||
{
|
||||
float pcfDepth = clamp(texture(shadowSampler, vec4(projCoords.xy + vec2(x, y) * texelSize, shadowMapIndex, projCoords.z - bias)),0,1);
|
||||
shadow += pcfDepth;
|
||||
}
|
||||
}
|
||||
shadow *= 1.0/9.0;
|
||||
return shadow;
|
||||
}
|
||||
//else
|
||||
//return 1;
|
||||
#else
|
||||
return texture(shadowSampler, vec4(projCoords.xy, shadowMapIndex, projCoords.z - bias));
|
||||
#endif
|
||||
}
|
||||
|
||||
float ShadowCalculationForAllSplitPlanes(const int lightIndex, const vec3 lightDirViewSpace, const vec3 normal, float lightIntensity, const sampler2DArrayShadow shadowSampler)
|
||||
{
|
||||
float distance = v.z;
|
||||
float bias = max(0.001 * (1.0 - dot(normal, lightDirViewSpace)), 0.0003);
|
||||
|
||||
bool applied = false;
|
||||
|
||||
for (int i = 0; i < NUM_SPLITS; i++)
|
||||
if(!applied && (distance < splitPlanes[i]))
|
||||
{
|
||||
//bias = ((i+1)*0.1)*0.001;
|
||||
lightIntensity *= ShadowCalculation(bias, i, lightIndex, shadowSampler);
|
||||
applied=true;
|
||||
//Graphics cards hate break (SLOW), hence boolean value above
|
||||
//break;
|
||||
}
|
||||
return lightIntensity;
|
||||
|
||||
}
|
||||
|
||||
//Parallax mapping with offset limiting
|
||||
//You can try different parallax mapping techniques, but they all have problems with steep angles so I decided this is something for later
|
||||
vec2 ParallaxMapping(vec3 V, vec2 T)
|
||||
{
|
||||
// get depth for this fragment
|
||||
float initialHeight = texture2D(heightMap, T).r-0.5;
|
||||
|
||||
// calculate amount of offset for Parallax Mapping With Offset Limiting
|
||||
vec2 texCoordOffset = HEIGHT_SCALE * V.xy * initialHeight;
|
||||
|
||||
// return modified texture coordinates
|
||||
return T + texCoordOffset;
|
||||
}
|
||||
|
||||
float DistributionGGX(float NdotH, float roughnessSquared)
|
||||
{
|
||||
float a = roughnessSquared;
|
||||
float a2 = a*a;
|
||||
float NdotH2 = NdotH*NdotH;
|
||||
|
||||
float nom = a2;
|
||||
float denom = NdotH2 * (a2 - 1.0) + 1.0;
|
||||
denom = PI * denom * denom + 0.0001;
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
|
||||
//"PBR Diffuse Lighting for GGX+Smith Microsurfaces", Earl Hammon, Jr.
|
||||
float GeometrySmithG2HammonDenom(float NdotL, float NdotV, float roughnessSquared)
|
||||
{
|
||||
float denom = mix(2*NdotL*NdotV,NdotL+NdotV,roughnessSquared);
|
||||
return denom;
|
||||
}
|
||||
|
||||
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
||||
{
|
||||
return F0 + (1.0 - F0) * pow(max(1.0 - cosTheta,0), 5.0);
|
||||
}
|
||||
|
||||
|
||||
vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
|
||||
{
|
||||
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0);
|
||||
}
|
||||
|
||||
struct LightValues
|
||||
{
|
||||
vec3 lightVec;
|
||||
vec3 lightDir;
|
||||
vec3 lightDirViewSpace;
|
||||
float attenFactor;
|
||||
float lightDist;
|
||||
};
|
||||
|
||||
LightValues CalculateLightValues(const int index)
|
||||
{
|
||||
LightValues result;
|
||||
if(glLightSource[index].spotCosTheta != -1.)
|
||||
{
|
||||
result.lightVec = glLightSource[index].position.xyz - v;
|
||||
result.lightDirViewSpace=normalize(result.lightVec);
|
||||
result.lightDist = length(result.lightVec);
|
||||
result.lightDir = normalize(result.lightVec);
|
||||
|
||||
float angle = max(dot(normalize(glLightSource[index].spotDirection), -result.lightDir),0);
|
||||
|
||||
if (angle > glLightSource[index].spotCosPhi)
|
||||
{
|
||||
float spotAtten;
|
||||
if (angle < glLightSource[index].spotCosTheta)
|
||||
spotAtten = (angle-glLightSource[index].spotCosPhi)/(glLightSource[index].spotCosTheta-glLightSource[index].spotCosPhi);
|
||||
else
|
||||
spotAtten = 1;
|
||||
|
||||
|
||||
if(glLightSource[index].spotExponent != 1.0)
|
||||
spotAtten = pow(spotAtten, glLightSource[index].spotExponent);
|
||||
|
||||
result.attenFactor = spotAtten * min(1.0/ (glLightSource[index].constantAttenuation +
|
||||
glLightSource[index].linearAttenuation * result.lightDist +
|
||||
glLightSource[index].quadraticAttenuation * result.lightDist * result.lightDist),1);
|
||||
}
|
||||
else
|
||||
result.attenFactor = 0.;
|
||||
}
|
||||
else if (glLightSource[index].position.w != 0.0)
|
||||
{
|
||||
result.lightVec = glLightSource[index].position.xyz - v;
|
||||
result.lightDirViewSpace=normalize(result.lightVec);
|
||||
result.lightDist = length(result.lightVec);
|
||||
|
||||
if (enableNormalMaps)
|
||||
result.lightVec = tbnMatrix*result.lightVec;
|
||||
result.lightDir = normalize(result.lightVec);
|
||||
|
||||
|
||||
// positional light source
|
||||
result.attenFactor = clamp(1.0/( glLightSource[index].constantAttenuation +
|
||||
glLightSource[index].linearAttenuation * result.lightDist +
|
||||
glLightSource[index].quadraticAttenuation * result.lightDist * result.lightDist ),0,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// directional light source
|
||||
result.attenFactor = 1.0;
|
||||
|
||||
if (enableNormalMaps)
|
||||
{
|
||||
result.lightDirViewSpace=normalize(glLightSource[index].position.xyz);
|
||||
result.lightVec = tbnMatrix*glLightSource[index].position.xyz;
|
||||
result.lightDir = normalize(result.lightVec);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.lightVec = glLightSource[index].position.xyz;
|
||||
result.lightDir = normalize(result.lightVec);
|
||||
result.lightDirViewSpace = result.lightDir;
|
||||
}
|
||||
result.lightDist = length(result.lightVec);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#if USE_CLUSTERED_SHADING == 1
|
||||
LightValues CalculateLightValuesClustered(const int index)
|
||||
{
|
||||
LightValues result;
|
||||
|
||||
result.lightVec = clusteredLights[index].position.xyz - v;
|
||||
result.lightDirViewSpace=normalize(result.lightVec);
|
||||
result.lightDist = length(result.lightVec);
|
||||
|
||||
if (enableNormalMaps)
|
||||
result.lightVec = tbnMatrix*result.lightVec;
|
||||
result.lightDir = normalize(result.lightVec);
|
||||
|
||||
// positional light source
|
||||
float inner = 0.0;
|
||||
float att = max(1.0 - max(0.0, (result.lightDist - inner) / (clusteredLights[index].position.w - inner)), 0.0);
|
||||
result.attenFactor = att;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
vec3 ApplyAmbientLight(const int index,const vec3 firstTexture, const float intensity, vec3 lightSum)
|
||||
{
|
||||
vec3 IAmbient = (matAmbientColor)*(PBR_FACTOR*glLightSource[index].ambient)*firstTexture;
|
||||
lightSum.rgb += IAmbient*intensity;
|
||||
return lightSum;
|
||||
}
|
||||
|
||||
vec3 ApplyPBRLight(vec3 lightDiffuseColor, const LightValues lightValues, const vec3 mapNormal, const vec3 eyeV, const vec3 F0, const float roughness, const vec3 IDiffuse, const vec3 firstTexture, vec3 lightSum, const float metalness)
|
||||
{
|
||||
|
||||
float visible = 1.0;
|
||||
float intensity = lightValues.attenFactor;
|
||||
|
||||
//vec3 IAmbient = (matAmbientColor.rgb)*(PBR_FACTOR*glLightSource[index].ambient)*firstTexture;
|
||||
//lightSum.rgb += IAmbient*intensity;
|
||||
|
||||
vec3 L = lightValues.lightDir;
|
||||
vec3 V = normalize(eyeV);
|
||||
vec3 H = normalize(L + V);
|
||||
|
||||
vec3 reflected;
|
||||
vec3 N = mapNormal;
|
||||
|
||||
float HdotV = max(dot(H, V), 0.0);
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float NdotV = max(dot(N, V), 0.0001);
|
||||
float NdotH = max(dot(N, H), 0.0001);
|
||||
|
||||
vec3 F = fresnelSchlick(HdotV, F0);
|
||||
|
||||
// Cook-Torrance BRDF
|
||||
float roughnessSquared = roughness*roughness;
|
||||
float NDF = DistributionGGX(NdotH, roughnessSquared);
|
||||
|
||||
vec3 nominator = NDF * F;
|
||||
float denominator = 2.0 * GeometrySmithG2HammonDenom(NdotV, NdotL, roughnessSquared) + 0.00001; // 0.00001 to prevent divide by zero.
|
||||
vec3 specular = nominator/denominator;
|
||||
|
||||
#ifndef SIMPLE_KD
|
||||
vec3 kD=mix(vec3(1.0)-F,vec3(0.0),metalness);
|
||||
#else
|
||||
float kD = 1.0 - metalness;
|
||||
#endif
|
||||
|
||||
#if USE_HQ_DIFFUSE == 1
|
||||
//GGX Diffuse Approximation from
|
||||
//"PBR Diffuse Lighting for GGX+Smith Microsurfaces, Earl Hammon, Jr."
|
||||
float LdotV = dot(L, V);
|
||||
float facing = 0.5+0.5*LdotV;
|
||||
float rough = facing*(0.9-0.4*facing)*(.5/(NdotH+0.05) + 1); //+0.05 to prevent too large values
|
||||
float smooth_ = 1.05*(1-pow(1-NdotL,5))*(1-pow(1-NdotV,5));
|
||||
float single = 1./PI*mix(smooth_, rough, roughnessSquared);
|
||||
float multi = 0.1159*roughnessSquared;
|
||||
vec3 diffuse = kD*IDiffuse.rgb*(single+IDiffuse.rgb*multi);
|
||||
#else
|
||||
vec3 diffuse = kD*IDiffuse.rgb/PI;
|
||||
#endif
|
||||
|
||||
lightSum+= PBR_FACTOR*lightDiffuseColor*(diffuse + specular)*intensity*NdotL;
|
||||
|
||||
|
||||
|
||||
return lightSum;
|
||||
}
|
||||
|
||||
vec3 ApplyLight(const int index, const LightValues lightValues, const vec3 mapNormal, const vec3 eyeV, const vec3 F0, const float roughness, const vec3 IDiffuse, const vec3 firstTexture, vec3 lightSum, const float metalness)
|
||||
{
|
||||
lightSum=ApplyAmbientLight(index, firstTexture, lightValues.attenFactor, lightSum);
|
||||
lightSum=ApplyPBRLight(glLightSource[index].diffuse.rgb, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse, firstTexture, lightSum, metalness);
|
||||
return lightSum;
|
||||
}
|
||||
|
||||
#if USE_CLUSTERED_SHADING == 1
|
||||
//Clustered shading code partially from
|
||||
//"Demo code implementing Clustered Forward Shading, accompanying the talk
|
||||
//'Tiled and Clustered Forward Shading' presented at Siggraph 2012."
|
||||
|
||||
/**
|
||||
* Computes the {i,j,k} integer index into the cluster grid. For details see our paper:
|
||||
* 'Clustered Deferred and Forward Shading'
|
||||
* http://www.cse.chalmers.se/~olaolss/main_frame.php?contents=publication&id=clustered_shading
|
||||
*/
|
||||
ivec3 calcClusterLoc(vec2 fragPos, float viewSpaceZ)
|
||||
{
|
||||
// i and j coordinates are just the same as tiled shading, and based on screen space position.
|
||||
ivec2 l = ivec2(int(fragPos.x) / LIGHT_GRID_TILE_DIM_X, int(fragPos.y) / LIGHT_GRID_TILE_DIM_Y);
|
||||
|
||||
// k is based on the log of the view space Z coordinate.
|
||||
float gridLocZ = log(viewSpaceZ * recNear) * recLogSD1;
|
||||
|
||||
return ivec3(l, int(gridLocZ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Linearlizes the 3D cluster location into an offset, which can be used as an
|
||||
* address into a linear buffer.
|
||||
*/
|
||||
int calcClusterOffset(ivec3 clusterLoc)
|
||||
{
|
||||
return (clusterLoc.z * LIGHT_GRID_MAX_DIM_Y + clusterLoc.y) * LIGHT_GRID_MAX_DIM_X + clusterLoc.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience shorthand function, see above...
|
||||
*/
|
||||
int calcClusterOffset(vec2 fragPos, float viewSpaceZ)
|
||||
{
|
||||
return calcClusterOffset(calcClusterLoc(fragPos, viewSpaceZ));
|
||||
}
|
||||
|
||||
vec3 ApplyClusteredLights(const vec3 mapNormal, const vec3 eyeV, const vec3 F0, const float roughness, const vec3 IDiffuse, const vec3 firstTexture, vec3 lightSum, const float metalness)
|
||||
{
|
||||
// fetch cluster data (i.e. offset to light indices, and numer of lights) from grid buffer.
|
||||
uvec2 offsetCount = texelFetch(clusterGridTex, calcClusterOffset(gl_FragCoord.xy, v.z)).xy;
|
||||
|
||||
int lightOffset = int(offsetCount.x);
|
||||
int lightCount = int(offsetCount.y);
|
||||
|
||||
for (int i = 0; i < lightCount; ++i)
|
||||
{
|
||||
// fetch light index from list of lights for the cluster.
|
||||
int lightIndex = texelFetch(clusterLightIndexListsTex, lightOffset + i).x;
|
||||
LightValues lightValues = CalculateLightValuesClustered(lightIndex);
|
||||
// compute and accumulate shading.
|
||||
lightSum = ApplyPBRLight(clusteredLights[lightIndex].diffuse.rgb*2, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse, firstTexture, lightSum, metalness);
|
||||
}
|
||||
|
||||
return lightSum;
|
||||
}
|
||||
#endif
|
||||
|
||||
void main(void)
|
||||
{
|
||||
float fogFactor = 0;
|
||||
if (enableFog && fogMode > 0)
|
||||
{
|
||||
//Radial fog
|
||||
float z = length(v);
|
||||
if (fogMode == 3)
|
||||
{
|
||||
fogFactor = (fogEnd - z) * fogScale;
|
||||
}
|
||||
else if (fogMode == 1)
|
||||
{
|
||||
fogFactor = 1.0/exp(glFog.density * z);
|
||||
}
|
||||
else if (fogMode == 2)
|
||||
{
|
||||
fogFactor = 1.0 /exp( (z * glFog.density)* (z * glFog.density));
|
||||
}
|
||||
|
||||
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec3 eyeV=normalize(eyeVec);
|
||||
vec3 normal=normalize(N);
|
||||
|
||||
vec2 texCoordsProcessed;
|
||||
|
||||
#if USE_PARALLAX_MAPS == 1
|
||||
if (enableParallaxMaps)
|
||||
texCoordsProcessed = ParallaxMapping(eyeV, texCoords.st);
|
||||
else
|
||||
#endif
|
||||
texCoordsProcessed = texCoords.st;
|
||||
|
||||
vec4 firstTexture;
|
||||
vec4 lightSum = vec4(0);
|
||||
if (enableFirstTexture)
|
||||
{
|
||||
firstTexture = texture2D(tex, texCoordsProcessed);
|
||||
if (enableSecondTexture)
|
||||
{
|
||||
if(tex2Mode == 0)
|
||||
{
|
||||
firstTexture *= texture2D(tex2, texCoords.pq);
|
||||
if (enableTex2Modulate2X)
|
||||
firstTexture.rgb*=4.6; //2^2.2 since rendering is gamma correct
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
lightSum.rgb += texture2D(tex2, texCoords.pq).rgb;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
firstTexture = vec4(1,1,1,1);
|
||||
}
|
||||
|
||||
float alpha = alphaValue*firstTexture.a;
|
||||
if (enableAlphaTest)
|
||||
if(alphaTestCompareMethod==5)
|
||||
{
|
||||
if( alpha <= alphaTestValue)
|
||||
discard;
|
||||
}
|
||||
else if(alphaTestCompareMethod==2)
|
||||
{
|
||||
if( alpha > alphaTestValue)
|
||||
discard;
|
||||
}
|
||||
else
|
||||
firstTexture =vec4(1,0,0,1);
|
||||
|
||||
vec3 mapNormal;
|
||||
if (enableNormalMaps)
|
||||
{
|
||||
vec3 textureNormal = texture2D(normalMap, texCoordsProcessed).rgb;
|
||||
textureNormal.xy = (textureNormal.rg * 2.0 - 1.0);
|
||||
textureNormal.z = sqrt(1.0-dot(textureNormal.xy,textureNormal.xy));
|
||||
mapNormal = normalize(textureNormal.xyz);
|
||||
}
|
||||
else
|
||||
mapNormal = normal;
|
||||
|
||||
lightSum+=vec4(((matEmissiveColor.rgb))* firstTexture.rgb, alpha);
|
||||
|
||||
float metalness;
|
||||
if (enableMetalnessMap)
|
||||
{
|
||||
metalness=texture2D(metalnessMap, texCoordsProcessed.st).r;
|
||||
}
|
||||
else
|
||||
{
|
||||
metalness=metalnessConst;
|
||||
|
||||
}
|
||||
|
||||
vec3 IDiffuse = (matDiffuseColor)*firstTexture.rgb;
|
||||
|
||||
float roughness;
|
||||
if (enableRoughnessMap)
|
||||
{
|
||||
roughness=clamp(roughnessTextureBias+texture2D(roughnessMap, texCoordsProcessed.st).r,0.0,1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
roughness=roughnessConst;
|
||||
}
|
||||
|
||||
#define DIELECTRIC_SPECULAR 0.04
|
||||
vec3 F0 = mix(vec3(DIELECTRIC_SPECULAR), IDiffuse, metalness);
|
||||
if (enableEnvMap)
|
||||
{
|
||||
vec3 n;
|
||||
if (enableNormalMaps)
|
||||
n=normalize( worldRotMat * (tbnMatrixObj * mapNormal ));
|
||||
else
|
||||
n=normalize(worldNormal);
|
||||
vec3 v = normalize( camPos - vWorld);
|
||||
vec3 reflectDir = reflect(-v, n);
|
||||
const float MAX_REFLECTION_LOD = 7;
|
||||
float lod = roughness * (2.0 - roughness) * MAX_REFLECTION_LOD;
|
||||
vec3 irradiance;
|
||||
vec3 radiance;
|
||||
if (enableFog)
|
||||
{
|
||||
vec3 ambientTint=PBR_FACTOR_ENV*glFog.color.rgb;
|
||||
irradiance = vec3(texture(irradianceMap, n).r)*ambientTint;
|
||||
radiance = vec3(textureLod(envMap, reflectDir, lod).r)*ambientTint;
|
||||
}
|
||||
else
|
||||
{
|
||||
irradiance = texture(irradianceMap, n).rgb*PBR_FACTOR_ENV;
|
||||
radiance = textureLod(envMap, reflectDir, lod).rgb*PBR_FACTOR_ENV;
|
||||
}
|
||||
|
||||
float NdotV = max(dot(n,v),0.0);
|
||||
vec2 brdf = texture(brdfLUT, vec2(NdotV, roughness)).rg;
|
||||
|
||||
#ifdef IBL_MULTIPLE_SCATTERING
|
||||
vec3 diffuseColor = mix(IDiffuse.rgb, vec3(0), metalness);
|
||||
// Multiple scattering, from:
|
||||
//"A Multiple-Scattering Microfacet Model for Real-Time Image-based Lighting", Carmelo J. Fdez-Agüera
|
||||
vec3 kS = F0;
|
||||
|
||||
vec3 FssEss = kS * brdf.x + brdf.y;
|
||||
|
||||
float Ess = brdf.x + brdf.y;
|
||||
float Ems = 1.0-Ess;
|
||||
vec3 Favg = F0 + (1.0-F0)/21.0;
|
||||
vec3 Fms = FssEss*Favg/(1.0-Ems*Favg);
|
||||
vec3 FmsEms = Fms * Ems;
|
||||
// Dielectrics
|
||||
vec3 Edss = 1.0 - (FssEss + FmsEms);
|
||||
vec3 kD = diffuseColor * Edss;
|
||||
// Composition
|
||||
lightSum.rgb += FssEss * radiance + (FmsEms+kD) * irradiance;
|
||||
#else
|
||||
vec3 diffuse = irradiance * IDiffuse;
|
||||
vec3 F = fresnelSchlickRoughness(NdotV, F0, roughness);
|
||||
#ifndef SIMPLE_KD
|
||||
vec3 kD=mix(vec3(1.0)-F,vec3(0.0),metalness);
|
||||
#else
|
||||
float kD = 1.0 - metalness;
|
||||
#endif
|
||||
|
||||
vec3 specular = radiance * (F0 * brdf.x + brdf.y);
|
||||
lightSum.rgb += kD*diffuse + specular;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (enableNormalMaps)
|
||||
{
|
||||
vec3 dir = vec3(0,0,1);
|
||||
float ambientIntensity = dot(dir,mapNormal);
|
||||
lightSum.rgb+=matAmbientColor.rgb * ambientColor.rgb* ambientIntensity*IDiffuse.rgb;
|
||||
}
|
||||
else
|
||||
lightSum.rgb+=matAmbientColor.rgb * ambientColor.rgb* IDiffuse.rgb;
|
||||
}
|
||||
|
||||
//Unrolled loop and a separated shadow pass to help some glsl compilers. Also some glsl compilers need a constant value (not variable!) for sampler arrays.
|
||||
if(lightCount > 0)
|
||||
{
|
||||
const int lightIndex = 0;
|
||||
LightValues lightValues = CalculateLightValues(lightIndex);
|
||||
#if MAX_SHADOWS > 0
|
||||
if (shadowCount > 0)
|
||||
lightValues.attenFactor = ShadowCalculationForAllSplitPlanes(lightIndex, lightValues.lightDirViewSpace, normal, lightValues.attenFactor, shadowMap[0]);
|
||||
#endif
|
||||
lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness);
|
||||
}
|
||||
if(lightCount > 1)
|
||||
{
|
||||
const int lightIndex = 1;
|
||||
LightValues lightValues = CalculateLightValues(lightIndex);
|
||||
#if MAX_SHADOWS > 1
|
||||
if (shadowCount > 1)
|
||||
lightValues.attenFactor = ShadowCalculationForAllSplitPlanes(lightIndex, lightValues.lightDirViewSpace, normal, lightValues.attenFactor, shadowMap[1]);
|
||||
#endif
|
||||
lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness);
|
||||
}
|
||||
if (lightCount > 2)
|
||||
{
|
||||
const int lightIndex = 2;
|
||||
LightValues lightValues = CalculateLightValues(lightIndex);
|
||||
lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness);
|
||||
}
|
||||
if (lightCount > 3)
|
||||
{
|
||||
const int lightIndex = 3;
|
||||
LightValues lightValues = CalculateLightValues(lightIndex);
|
||||
lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness);
|
||||
}
|
||||
if (lightCount > 4)
|
||||
{
|
||||
const int lightIndex = 4;
|
||||
LightValues lightValues = CalculateLightValues(lightIndex);
|
||||
lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness);
|
||||
}
|
||||
if (lightCount > 5)
|
||||
{
|
||||
const int lightIndex = 5;
|
||||
LightValues lightValues = CalculateLightValues(lightIndex);
|
||||
lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness);
|
||||
}
|
||||
if (lightCount > 6)
|
||||
{
|
||||
const int lightIndex = 6;
|
||||
LightValues lightValues = CalculateLightValues(lightIndex);
|
||||
lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness);
|
||||
}
|
||||
if (lightCount > 7)
|
||||
{
|
||||
const int lightIndex = 7;
|
||||
LightValues lightValues = CalculateLightValues(lightIndex);
|
||||
lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness);
|
||||
}
|
||||
#if USE_CLUSTERED_SHADING == 1
|
||||
if(enableClusteredShading)
|
||||
lightSum.rgb = ApplyClusteredLights(mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness);
|
||||
#endif
|
||||
|
||||
vec4 finalColor = lightSum;
|
||||
|
||||
|
||||
if (enableFog && fogMode > 0)
|
||||
{
|
||||
finalColor = mix(vec4(glFog.color,1.0),finalColor, fogFactor);
|
||||
}
|
||||
|
||||
diffuseColorOut=vec4(ToGammaCorrected(finalColor.rgb),finalColor.a);
|
||||
}
|
||||
145
FLARDATA/Shader/lighting.vs
Normal file
145
FLARDATA/Shader/lighting.vs
Normal file
@@ -0,0 +1,145 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//PBR lighting shader for FLAR by Schmackbolzen
|
||||
|
||||
#version 330
|
||||
|
||||
#define MAX_SHADOWS $MAX_SHADOWS
|
||||
#define NUM_SPLITS $NUM_SPLITS
|
||||
|
||||
out vec3 eyeVec;
|
||||
out vec3 v,vWorld,worldNormal;
|
||||
out mat3 tbnMatrix,tbnMatrixObj;
|
||||
out vec3 N;
|
||||
out vec4 shadowCoord[MAX_SHADOWS*NUM_SPLITS];
|
||||
out vec4 texCoords;
|
||||
out mat3 worldRotMat;
|
||||
out float alphaValue;
|
||||
out float fogEnd;
|
||||
out float fogScale;
|
||||
|
||||
struct glFogParameters
|
||||
{
|
||||
vec3 color;
|
||||
float density;
|
||||
float start;
|
||||
float end;
|
||||
};
|
||||
|
||||
uniform glFogParameters glFog;
|
||||
uniform mat4 depthBiasMVP[MAX_SHADOWS*NUM_SPLITS];
|
||||
uniform mat4 modelViewMat;
|
||||
uniform mat4 projectionMat;
|
||||
uniform mat4 invViewMat;
|
||||
uniform mat4 textureMatrix[2];
|
||||
uniform bool enableNormalMaps;
|
||||
uniform int shadowCount;
|
||||
uniform bool enableEnvMap;
|
||||
uniform bool isInstanced;
|
||||
uniform bool isInstancedTransparent;
|
||||
uniform bool isInstancedFog;
|
||||
uniform float matDiffuseAlpha;
|
||||
uniform int tex2Mode;
|
||||
uniform int texture1Index;
|
||||
|
||||
layout (location = 0) in vec4 inPosition;
|
||||
layout (location = 1) in vec3 inNormal;
|
||||
layout (location = 2) in vec4 inColor;
|
||||
layout (location = 3) in vec4 inSecondColor;
|
||||
layout (location = 4) in vec4 inTexCoord0;
|
||||
layout (location = 5) in vec4 inTexCoord2;
|
||||
layout (location = 6) in mat4 inModelViewMatInstanced;
|
||||
layout (location = 10) in float inAlphaValueInstanced;
|
||||
layout (location = 11) in vec2 inFogStartEndInstanced;
|
||||
|
||||
const mat4 biasMatrix = mat4(0.5f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.5f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.5f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f);
|
||||
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
||||
|
||||
mat4 mv;
|
||||
if(!isInstanced)
|
||||
mv=modelViewMat;
|
||||
else
|
||||
mv=inModelViewMatInstanced;
|
||||
|
||||
if(!isInstancedTransparent)
|
||||
{
|
||||
alphaValue = matDiffuseAlpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
alphaValue = inAlphaValueInstanced;
|
||||
}
|
||||
|
||||
if(!isInstancedFog)
|
||||
{
|
||||
fogEnd = glFog.end;
|
||||
fogScale = 1 / (glFog.end - glFog.start);
|
||||
}
|
||||
else
|
||||
{
|
||||
fogEnd = inFogStartEndInstanced.y;
|
||||
fogScale = 1 / (inFogStartEndInstanced.y - inFogStartEndInstanced.x);
|
||||
}
|
||||
|
||||
mat3 normalMat = mat3(mv);
|
||||
v = vec3(mv * inPosition);
|
||||
mat4 worldMat = invViewMat*mv;
|
||||
if(enableEnvMap)
|
||||
{
|
||||
vWorld = vec3(worldMat * inPosition);
|
||||
worldRotMat = mat3(worldMat);
|
||||
worldNormal = worldRotMat * inNormal;
|
||||
}
|
||||
if (shadowCount > 0)
|
||||
{
|
||||
for(int i=0;i<NUM_SPLITS;i++)
|
||||
shadowCoord[i] = biasMatrix*depthBiasMVP[i] * worldMat * inPosition;
|
||||
if (shadowCount > 1)
|
||||
for(int i=0;i<NUM_SPLITS;i++)
|
||||
shadowCoord[NUM_SPLITS+i] = biasMatrix*depthBiasMVP[NUM_SPLITS+i] * worldMat * inPosition;
|
||||
}
|
||||
N = normalize(normalMat*inNormal);
|
||||
|
||||
if (enableNormalMaps)
|
||||
{
|
||||
vec3 TO = normalize(vec3(inTexCoord2.s,inTexCoord2.t,inTexCoord2.p));
|
||||
//TO = normalize(TO - dot(TO, inNormal) * inNormal);
|
||||
vec3 BO = normalize(cross(inNormal,TO)*(inTexCoord2.q));
|
||||
vec3 TA=normalMat*TO;
|
||||
vec3 BA=normalMat*BO;
|
||||
vec3 T=normalize(TA);
|
||||
vec3 B=normalize(BA);
|
||||
tbnMatrix = mat3(T.x, B.x, N.x,
|
||||
T.y, B.y, N.y,
|
||||
T.z, B.z, N.z);
|
||||
|
||||
tbnMatrixObj = mat3(TO,BO,inNormal.xyz);
|
||||
|
||||
|
||||
eyeVec = tbnMatrix*(-v);
|
||||
}
|
||||
else
|
||||
eyeVec = -v;
|
||||
|
||||
gl_Position = projectionMat * mv * inPosition;
|
||||
|
||||
vec4 texCoords0=vec4(inTexCoord0.xy,0,1);
|
||||
vec4 texCoords1=vec4(inTexCoord0.zw,0,1);
|
||||
|
||||
texCoords.xy = (textureMatrix[0]*texCoords0).xy;
|
||||
|
||||
//texCoords.zw = (textureMatrix[1]*vec4(inTexCoord0.zw,0,1)).zw;
|
||||
|
||||
if (texture1Index == 0)
|
||||
texCoords.zw = (textureMatrix[1]*texCoords0).xy;
|
||||
else if (texture1Index == 1)
|
||||
texCoords.zw = (textureMatrix[1]*texCoords1).zw;
|
||||
}
|
||||
13
FLARDATA/Shader/noMaterial.fp
Normal file
13
FLARDATA/Shader/noMaterial.fp
Normal file
@@ -0,0 +1,13 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//No material shader for FLAR by Schmackbolzen
|
||||
|
||||
#version 330
|
||||
|
||||
uniform vec3 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(color,1);
|
||||
}
|
||||
23
FLARDATA/Shader/noMaterial.vs
Normal file
23
FLARDATA/Shader/noMaterial.vs
Normal file
@@ -0,0 +1,23 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//No material shader for FLAR by Schmackbolzen
|
||||
|
||||
#version 330
|
||||
|
||||
uniform mat4 modelViewMat;
|
||||
uniform mat4 projectionMat;
|
||||
uniform bool isInstanced;
|
||||
|
||||
layout (location = 0) in vec4 inPosition;
|
||||
layout (location = 6) in mat4 inModelViewMatInstanced;
|
||||
|
||||
void main()
|
||||
{
|
||||
mat4 mv;
|
||||
if(!isInstanced)
|
||||
mv=modelViewMat;
|
||||
else
|
||||
mv=inModelViewMatInstanced;
|
||||
gl_Position = projectionMat * mv * inPosition;
|
||||
}
|
||||
130
FLARDATA/Shader/postProcess.fp
Normal file
130
FLARDATA/Shader/postProcess.fp
Normal file
@@ -0,0 +1,130 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Post processing shader for FLAR by Schmackbolzen
|
||||
//Sources are mentioned in the comments
|
||||
|
||||
#version 330
|
||||
#include "ColorConversion.inc"
|
||||
#define USE_ACES_CURVE $USE_ACES_CURVE
|
||||
#define USE_PBR_BLOOM $USE_PBR_BLOOM
|
||||
|
||||
in vec2 TexCoords;
|
||||
|
||||
uniform sampler2D scene;
|
||||
#if USE_PBR_BLOOM == 1
|
||||
uniform sampler2D bloomtex;
|
||||
#endif
|
||||
uniform float exposure;
|
||||
uniform float exposureLowerLimit;
|
||||
|
||||
//https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
|
||||
//ACES fit by Steven Hill
|
||||
|
||||
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
|
||||
const mat3 ACESInputMat = mat3(
|
||||
0.59719, 0.07600, 0.02840,
|
||||
0.35458, 0.90834, 0.13383,
|
||||
0.04823, 0.01566, 0.83777);
|
||||
|
||||
// ODT_SAT => XYZ => D60_2_D65 => sRGB
|
||||
const mat3 ACESOutputMat = mat3(
|
||||
1.60475, -0.10208, -0.00327,
|
||||
-0.53108, 1.10813, -0.07276,
|
||||
-0.07367, -0.00605, 1.07602
|
||||
);
|
||||
|
||||
vec3 RRTAndODTFit(vec3 v)
|
||||
{
|
||||
vec3 a = v * (v + 0.0245786f) - 0.000090537f;
|
||||
vec3 b = v * (0.983729f * v + 0.4329510f) + 0.238081f;
|
||||
return a / b;
|
||||
}
|
||||
|
||||
vec3 ACESFitted(vec3 color)
|
||||
{
|
||||
color = ACESInputMat * color;
|
||||
|
||||
// Apply RRT and ODT
|
||||
color = RRTAndODTFit(color);
|
||||
|
||||
color = ACESOutputMat * color;
|
||||
|
||||
// Clamp to [0, 1]
|
||||
color = clamp(color,0.,1.);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Uchimura 2017, "HDR theory and practice"
|
||||
// Math: https://www.desmos.com/calculator/gslcdxvipg
|
||||
// Source: https://www.slideshare.net/nikuque/hdr-theory-and-practicce-jp
|
||||
// Used in "Gran Turismo Sport" game
|
||||
vec3 uchimura(vec3 x, float P, float a, float m, float l, float c, float b) {
|
||||
float l0 = ((P - m) * l) / a;
|
||||
float L0 = m - m / a;
|
||||
float L1 = m + (1.0 - m) / a;
|
||||
float S0 = m + l0;
|
||||
float S1 = m + a * l0;
|
||||
float C2 = (a * P) / (P - S1);
|
||||
float CP = -C2 / P;
|
||||
|
||||
vec3 w0 = vec3(1.0 - smoothstep(0.0, m, x));
|
||||
vec3 w2 = vec3(step(m + l0, x));
|
||||
vec3 w1 = vec3(1.0 - w0 - w2);
|
||||
|
||||
vec3 T = vec3(m * pow(x / m, vec3(c)) + b);
|
||||
vec3 S = vec3(P - (P - S1) * exp(CP * (x - S0)));
|
||||
vec3 L = vec3(m + a * (x - m));
|
||||
|
||||
return T * w0 + L * w1 + S * w2;
|
||||
}
|
||||
|
||||
vec3 uchimura(vec3 x) {
|
||||
const float P = 1.0; // max display brightness
|
||||
const float a = 1.0; // contrast
|
||||
const float m = 0.22; // linear section start
|
||||
const float l = 0.4; // linear section length
|
||||
const float c = 1.33; // black
|
||||
const float b = 0.0; // pedestal
|
||||
|
||||
return uchimura(x, P, a, m, l, c, b);
|
||||
}
|
||||
|
||||
#if USE_PBR_BLOOM == 1
|
||||
const float bloomStrength = 0.2f;
|
||||
vec4 bloom_new()
|
||||
{
|
||||
vec4 hdrColor = texture(scene, TexCoords);
|
||||
//hdrColor.rgb=vec3(0);
|
||||
vec3 bloomColor = texture(bloomtex, TexCoords).rgb;
|
||||
//Blend in linear space
|
||||
/*hdrColor.rgb=ToLinear(hdrColor.rgb);
|
||||
bloomColor=ToLinear(bloomColor);*/
|
||||
vec4 blended=vec4(mix(hdrColor.rgb, bloomColor, bloomStrength),hdrColor.a); // linear interpolation
|
||||
//Blend in gamma corrected space
|
||||
blended.rgb=ToLinear(blended.rgb);
|
||||
return blended;
|
||||
}
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
#if USE_PBR_BLOOM == 0
|
||||
vec4 color = texture2D(scene, TexCoords);
|
||||
//Not a nice solution to convert two times (ideally there would be none), but not easily solvable currently
|
||||
color.rgb = ToLinear(color.rgb);
|
||||
#else
|
||||
vec4 color = bloom_new();
|
||||
#endif
|
||||
//Exposure is chosen so that both curves have about the same brightness and the look is fine with very bright starspheres like in Tau-37
|
||||
#if USE_ACES_CURVE == 1
|
||||
color.rgb=ACESFitted((exposure)*color.rgb);
|
||||
#else
|
||||
color.rgb=uchimura((exposure)*color.rgb);
|
||||
#endif
|
||||
|
||||
color.rgb=ToGammaCorrected(color.rgb);
|
||||
gl_FragColor = color;
|
||||
|
||||
}
|
||||
16
FLARDATA/Shader/postProcess.vs
Normal file
16
FLARDATA/Shader/postProcess.vs
Normal file
@@ -0,0 +1,16 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Post processing shader for FLAR by Schmackbolzen
|
||||
|
||||
#version 330
|
||||
layout (location = 0) in vec4 vertex;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vertex.xy, 1.0f, 1.0f);
|
||||
vec2 texture = vertex.zw;
|
||||
TexCoords = texture;
|
||||
}
|
||||
46
FLARDATA/Shader/postProcessLightScatter.fp
Normal file
46
FLARDATA/Shader/postProcessLightScatter.fp
Normal file
@@ -0,0 +1,46 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Code based on https://fabiensanglard.net/lightScattering/index.php which is based on
|
||||
//"Volumetric Light Scattering as a Post-Process" GPU Gems 3 (2005) and
|
||||
//"Light Shaft Rendering" ShadersX3 (2004).
|
||||
|
||||
#version 330
|
||||
#define MAX_NUM_LIGHTS $MAX_NUM_LIGHTS
|
||||
in vec2 TexCoords;
|
||||
|
||||
uniform float exposure;
|
||||
uniform float decay;
|
||||
uniform float density;
|
||||
uniform float weight;
|
||||
uniform vec2 lightPositionOnScreen[MAX_NUM_LIGHTS];
|
||||
uniform sampler2D myTexture;
|
||||
uniform int numActiveLights;
|
||||
|
||||
const int NUM_SAMPLES = 75;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 result = vec4(0);
|
||||
|
||||
for (int lightIndex = 0; lightIndex < MAX_NUM_LIGHTS && lightIndex < numActiveLights; lightIndex++ )
|
||||
{
|
||||
vec2 deltaTextCoord = vec2( TexCoords.st - lightPositionOnScreen[lightIndex].xy );
|
||||
vec2 textCoord = TexCoords.st;
|
||||
deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * density;
|
||||
float illuminationDecay = 1.0;
|
||||
|
||||
for(int i=0; i < NUM_SAMPLES ; i++)
|
||||
{
|
||||
textCoord -= deltaTextCoord;
|
||||
vec4 sample = texture2D(myTexture, textCoord );
|
||||
sample *= illuminationDecay * weight;
|
||||
result += sample;
|
||||
illuminationDecay *= decay;
|
||||
}
|
||||
}
|
||||
|
||||
result=min(result,vec4(NUM_SAMPLES*weight));
|
||||
result *= exposure;
|
||||
gl_FragColor = result;
|
||||
}
|
||||
18
FLARDATA/Shader/postProcessLightScatter.vs
Normal file
18
FLARDATA/Shader/postProcessLightScatter.vs
Normal file
@@ -0,0 +1,18 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Code based on https://fabiensanglard.net/lightScattering/index.php which is based on
|
||||
//"Volumetric Light Scattering as a Post-Process" GPU Gems 3 (2005) and
|
||||
//"Light Shaft Rendering" ShadersX3 (2004).
|
||||
|
||||
#version 330
|
||||
layout (location = 0) in vec4 vertex;
|
||||
|
||||
out vec2 TexCoords;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vertex.xy, 0.0f, 1.0f);
|
||||
vec2 texture = vertex.zw;
|
||||
TexCoords = texture;
|
||||
}
|
||||
129
FLARDATA/Shader/prefilter.fp
Normal file
129
FLARDATA/Shader/prefilter.fp
Normal file
@@ -0,0 +1,129 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//Code based on https://learnopengl.com/PBR/IBL/Specular-IBL
|
||||
|
||||
#version 330
|
||||
in vec3 WorldPos;
|
||||
|
||||
uniform samplerCube environmentMap;
|
||||
uniform float roughness;
|
||||
uniform bool convertToLinear;
|
||||
uniform bool copyOnly;
|
||||
|
||||
const float PI = 3.14159265359;
|
||||
|
||||
vec3 ToGammaCorrected(vec3 inColor){
|
||||
return pow(inColor.rgb,1./vec3(2.2));
|
||||
}
|
||||
|
||||
vec3 ToLinear(vec3 inColor){
|
||||
return pow(inColor,vec3(2.2));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
float DistributionGGX(vec3 N, vec3 H, float roughness)
|
||||
{
|
||||
float a = roughness*roughness;
|
||||
float a2 = a*a;
|
||||
float NdotH = max(dot(N, H), 0.0);
|
||||
float NdotH2 = NdotH*NdotH;
|
||||
|
||||
float nom = a2;
|
||||
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||
denom = PI * denom * denom + 0.0001;
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
|
||||
// efficient VanDerCorpus calculation.
|
||||
float RadicalInverse_VdC(uint bits)
|
||||
{
|
||||
bits = (bits << 16u) | (bits >> 16u);
|
||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
vec2 Hammersley(uint i, uint N)
|
||||
{
|
||||
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
|
||||
{
|
||||
float a = roughness*roughness;
|
||||
|
||||
float phi = 2.0 * PI * Xi.x;
|
||||
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
|
||||
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
|
||||
|
||||
// from spherical coordinates to cartesian coordinates - halfway vector
|
||||
vec3 H;
|
||||
H.x = cos(phi) * sinTheta;
|
||||
H.y = sin(phi) * sinTheta;
|
||||
H.z = cosTheta;
|
||||
|
||||
// from tangent-space H vector to world-space sample vector
|
||||
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 tangent = normalize(cross(up, N));
|
||||
vec3 bitangent = cross(N, tangent);
|
||||
|
||||
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
||||
return normalize(sampleVec);
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
void main()
|
||||
{
|
||||
vec3 N = normalize(WorldPos);
|
||||
|
||||
// make the simplyfying assumption that V equals R equals the normal
|
||||
vec3 R = N;
|
||||
vec3 V = R;
|
||||
|
||||
if (!copyOnly)
|
||||
{
|
||||
const uint SAMPLE_COUNT = 1024u;
|
||||
vec3 prefilteredColor = vec3(0.0);
|
||||
float totalWeight = 0.0;
|
||||
|
||||
for(uint i = 0u; i < SAMPLE_COUNT; ++i)
|
||||
{
|
||||
// generates a sample vector that's biased towards the preferred alignment direction (importance sampling).
|
||||
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
|
||||
vec3 H = ImportanceSampleGGX(Xi, N, roughness);
|
||||
vec3 L = normalize(2.0 * dot(V, H) * H - V);
|
||||
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
if(NdotL > 0.0)
|
||||
{
|
||||
// sample from the environment's mip level based on roughness/pdf
|
||||
float D = DistributionGGX(N, H, roughness);
|
||||
float NdotH = max(dot(N, H), 0.0);
|
||||
float HdotV = max(dot(H, V), 0.0);
|
||||
float pdf = D * NdotH / (4.0 * HdotV + 0.0001);
|
||||
|
||||
float resolution = 1024.0; // resolution of source cubemap (per face)
|
||||
float saTexel = 4.0 * PI / (6.0 * resolution * resolution);
|
||||
float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001);
|
||||
|
||||
float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
|
||||
vec3 texColor=textureLod(environmentMap, L, mipLevel).rgb;
|
||||
if(convertToLinear)
|
||||
texColor=ToLinear(texColor);
|
||||
prefilteredColor += texColor * NdotL;
|
||||
totalWeight += NdotL;
|
||||
}
|
||||
}
|
||||
|
||||
prefilteredColor = prefilteredColor / totalWeight;
|
||||
|
||||
gl_FragColor = vec4(ToGammaCorrected(prefilteredColor), 1.0);
|
||||
//gl_FragColor = vec4(prefilteredColor, 1.0);
|
||||
}
|
||||
else
|
||||
gl_FragColor = vec4(textureLod(environmentMap, V, 0).rgb, 1.0);
|
||||
}
|
||||
14
FLARDATA/Shader/simpleColor.fp
Normal file
14
FLARDATA/Shader/simpleColor.fp
Normal file
@@ -0,0 +1,14 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//
|
||||
//Simple color shader for FLAR by Schmackbolzen
|
||||
|
||||
#version 330
|
||||
|
||||
in vec3 currentColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(currentColor,1);
|
||||
}
|
||||
36
FLARDATA/Shader/simpleColor.vs
Normal file
36
FLARDATA/Shader/simpleColor.vs
Normal file
@@ -0,0 +1,36 @@
|
||||
//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen
|
||||
//If you use the supplied shader files you may not modify them unless you state in them what you changed
|
||||
//and also mention the source or who the author is.
|
||||
//
|
||||
//Simple color shader for FLAR by Schmackbolzen
|
||||
|
||||
#version 330
|
||||
|
||||
uniform mat4 modelViewMat;
|
||||
uniform mat4 projectionMat;
|
||||
uniform vec3 position;
|
||||
uniform vec3 color;
|
||||
uniform float size;
|
||||
uniform bool isInstanced;
|
||||
|
||||
layout (location = 0) in vec3 inVertex;
|
||||
layout (location = 1) in vec3 inPositionInstanced;
|
||||
layout (location = 2) in float inSizeInstanced;
|
||||
layout (location = 3) in vec3 inColorInstanced;
|
||||
out vec3 currentColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 worldSpacePos;
|
||||
if(!isInstanced)
|
||||
{
|
||||
currentColor=color;
|
||||
worldSpacePos=size * inVertex + position;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentColor=inColorInstanced;
|
||||
worldSpacePos=inSizeInstanced * inVertex + inPositionInstanced;
|
||||
}
|
||||
gl_Position = projectionMat * modelViewMat * vec4(worldSpacePos,1);
|
||||
}
|
||||
Reference in New Issue
Block a user