mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
- move material light modes to their own subshader lumps
This commit is contained in:
parent
eb39e88682
commit
07fa310f23
7 changed files with 415 additions and 425 deletions
|
@ -134,7 +134,7 @@ static FString RemoveLegacyUserUniforms(FString code)
|
|||
return code;
|
||||
}
|
||||
|
||||
bool FShader::Load(const char * name, const char * vert_prog_lump, const char * frag_prog_lump, const char * proc_prog_lump, const char * defines)
|
||||
bool FShader::Load(const char * name, const char * vert_prog_lump, const char * frag_prog_lump, const char * proc_prog_lump, const char * light_fragprog, const char * defines)
|
||||
{
|
||||
static char buffer[10000];
|
||||
FString error;
|
||||
|
@ -346,6 +346,14 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
|||
}
|
||||
}
|
||||
|
||||
if (light_fragprog)
|
||||
{
|
||||
int pp_lump = Wads.CheckNumForFullName(light_fragprog);
|
||||
if (pp_lump == -1) I_Error("Unable to load '%s'", light_fragprog);
|
||||
FMemLump pp_data = Wads.ReadLump(pp_lump);
|
||||
fp_comb << pp_data.GetString().GetChars() << "\n";
|
||||
}
|
||||
|
||||
if (gl.flags & RFL_NO_CLIP_PLANES)
|
||||
{
|
||||
// On ATI's GL3 drivers we have to disable gl_ClipDistance because it's hopelessly broken.
|
||||
|
@ -514,7 +522,7 @@ bool FShader::Bind()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderPath, const char *shaderdefines, bool usediscard, EPassType passType)
|
||||
FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType)
|
||||
{
|
||||
FString defines;
|
||||
defines += shaderdefines;
|
||||
|
@ -527,7 +535,7 @@ FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderP
|
|||
try
|
||||
{
|
||||
shader = new FShader(ShaderName);
|
||||
if (!shader->Load(ShaderName, "shaders/glsl/main.vp", "shaders/glsl/main.fp", ShaderPath, defines.GetChars()))
|
||||
if (!shader->Load(ShaderName, "shaders/glsl/main.vp", "shaders/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars()))
|
||||
{
|
||||
I_FatalError("Unable to load shader %s\n", ShaderName);
|
||||
}
|
||||
|
@ -564,30 +572,31 @@ struct FDefaultShader
|
|||
{
|
||||
const char * ShaderName;
|
||||
const char * gettexelfunc;
|
||||
const char * lightfunc;
|
||||
const char * Defines;
|
||||
};
|
||||
|
||||
// Note: the MaterialShaderIndex enum in gl_shader.h needs to be updated whenever this array is modified.
|
||||
static const FDefaultShader defaultshaders[]=
|
||||
{
|
||||
{"Default", "shaders/glsl/func_normal.fp", ""},
|
||||
{"Warp 1", "shaders/glsl/func_warp1.fp", ""},
|
||||
{"Warp 2", "shaders/glsl/func_warp2.fp", ""},
|
||||
{"Brightmap","shaders/glsl/func_brightmap.fp", ""},
|
||||
{"Specular","shaders/glsl/func_normal.fp", "#define SPECULAR\n"},
|
||||
{"SpecularBrightmap","shaders/glsl/func_brightmap.fp", "#define SPECULAR\n"},
|
||||
{"PBR","shaders/glsl/func_normal.fp", "#define PBR\n"},
|
||||
{"PBRBrightmap","shaders/glsl/func_brightmap.fp", "#define PBR\n"},
|
||||
{"No Texture", "shaders/glsl/func_notexture.fp", ""},
|
||||
{"Basic Fuzz", "shaders/glsl/fuzz_standard.fp", ""},
|
||||
{"Smooth Fuzz", "shaders/glsl/fuzz_smooth.fp", ""},
|
||||
{"Swirly Fuzz", "shaders/glsl/fuzz_swirly.fp", ""},
|
||||
{"Translucent Fuzz", "shaders/glsl/fuzz_smoothtranslucent.fp", ""},
|
||||
{"Jagged Fuzz", "shaders/glsl/fuzz_jagged.fp", ""},
|
||||
{"Noise Fuzz", "shaders/glsl/fuzz_noise.fp", ""},
|
||||
{"Smooth Noise Fuzz", "shaders/glsl/fuzz_smoothnoise.fp", ""},
|
||||
{"Software Fuzz", "shaders/glsl/fuzz_software.fp", ""},
|
||||
{NULL,NULL,NULL}
|
||||
{"Default", "shaders/glsl/func_normal.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Warp 1", "shaders/glsl/func_warp1.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Warp 2", "shaders/glsl/func_warp2.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Brightmap","shaders/glsl/func_brightmap.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Specular", "shaders/glsl/func_normal.fp", "shaders/glsl/material_specular.fp", "#define SPECULAR\n#define NORMALMAP\n"},
|
||||
{"SpecularBrightmap", "shaders/glsl/func_brightmap.fp", "shaders/glsl/material_specular.fp", "#define SPECULAR\n#define NORMALMAP\n"},
|
||||
{"PBR","shaders/glsl/func_normal.fp", "shaders/glsl/material_pbr.fp", "#define PBR\n#define NORMALMAP\n"},
|
||||
{"PBRBrightmap","shaders/glsl/func_brightmap.fp", "shaders/glsl/material_pbr.fp", "#define PBR\n#define NORMALMAP\n"},
|
||||
{"No Texture", "shaders/glsl/func_notexture.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Basic Fuzz", "shaders/glsl/fuzz_standard.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Smooth Fuzz", "shaders/glsl/fuzz_smooth.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Swirly Fuzz", "shaders/glsl/fuzz_swirly.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Translucent Fuzz", "shaders/glsl/fuzz_smoothtranslucent.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Jagged Fuzz", "shaders/glsl/fuzz_jagged.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Noise Fuzz", "shaders/glsl/fuzz_noise.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Smooth Noise Fuzz", "shaders/glsl/fuzz_smoothnoise.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Software Fuzz", "shaders/glsl/fuzz_software.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{nullptr,nullptr,nullptr,nullptr}
|
||||
};
|
||||
|
||||
static TArray<FString> usershaders;
|
||||
|
@ -598,15 +607,16 @@ struct FEffectShader
|
|||
const char *vp;
|
||||
const char *fp1;
|
||||
const char *fp2;
|
||||
const char *fp3;
|
||||
const char *defines;
|
||||
};
|
||||
|
||||
static const FEffectShader effectshaders[]=
|
||||
{
|
||||
{ "fogboundary", "shaders/glsl/main.vp", "shaders/glsl/fogboundary.fp", NULL, "#define NO_ALPHATEST\n" },
|
||||
{ "spheremap", "shaders/glsl/main.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "#define SPHEREMAP\n#define NO_ALPHATEST\n" },
|
||||
{ "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", NULL, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||
{ "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", NULL, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||
{ "fogboundary", "shaders/glsl/main.vp", "shaders/glsl/fogboundary.fp", nullptr, nullptr, "#define NO_ALPHATEST\n" },
|
||||
{ "spheremap", "shaders/glsl/main.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "shaders/glsl/material_normal.fp", "#define SPHEREMAP\n#define NO_ALPHATEST\n" },
|
||||
{ "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||
{ "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||
};
|
||||
|
||||
FShaderManager::FShaderManager()
|
||||
|
@ -726,11 +736,11 @@ void FShaderCollection::CompileShaders(EPassType passType)
|
|||
|
||||
for(int i=0;defaultshaders[i].ShaderName != NULL;i++)
|
||||
{
|
||||
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].Defines, true, passType);
|
||||
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, passType);
|
||||
mMaterialShaders.Push(shc);
|
||||
if (i < SHADER_NoTexture)
|
||||
{
|
||||
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].Defines, false, passType);
|
||||
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType);
|
||||
mMaterialShadersNAT.Push(shc);
|
||||
}
|
||||
}
|
||||
|
@ -740,7 +750,7 @@ void FShaderCollection::CompileShaders(EPassType passType)
|
|||
FString name = ExtractFileBase(usershaders[i]);
|
||||
FName sfn = name;
|
||||
|
||||
FShader *shc = Compile(sfn, usershaders[i], "", true, passType);
|
||||
FShader *shc = Compile(sfn, usershaders[i], "shaders/glsl/material_normal.fp", "", true, passType);
|
||||
mMaterialShaders.Push(shc);
|
||||
}
|
||||
|
||||
|
@ -748,7 +758,7 @@ void FShaderCollection::CompileShaders(EPassType passType)
|
|||
{
|
||||
FShader *eff = new FShader(effectshaders[i].ShaderName);
|
||||
if (!eff->Load(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1,
|
||||
effectshaders[i].fp2, effectshaders[i].defines))
|
||||
effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines))
|
||||
{
|
||||
delete eff;
|
||||
}
|
||||
|
|
|
@ -317,7 +317,7 @@ public:
|
|||
|
||||
~FShader();
|
||||
|
||||
bool Load(const char * name, const char * vert_prog_lump, const char * fragprog, const char * fragprog2, const char *defines);
|
||||
bool Load(const char * name, const char * vert_prog_lump, const char * fragprog, const char * fragprog2, const char * light_fragprog, const char *defines);
|
||||
|
||||
void SetColormapColor(float r, float g, float b, float r1, float g1, float b1);
|
||||
void SetGlowParams(float *topcolors, float topheight, float *bottomcolors, float bottomheight);
|
||||
|
@ -367,7 +367,7 @@ class FShaderCollection
|
|||
public:
|
||||
FShaderCollection(EPassType passType);
|
||||
~FShaderCollection();
|
||||
FShader *Compile(const char *ShaderName, const char *ShaderPath, const char *shaderdefines, bool usediscard, EPassType passType);
|
||||
FShader *Compile(const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType);
|
||||
int Find(const char *mame);
|
||||
FShader *BindEffect(int effect);
|
||||
void ApplyMatrices(VSMatrix *proj, VSMatrix *view);
|
||||
|
|
|
@ -15,7 +15,7 @@ out vec4 FragNormal;
|
|||
vec4 Process(vec4 color);
|
||||
vec4 ProcessTexel();
|
||||
vec4 ProcessLight(vec4 color);
|
||||
|
||||
vec3 ProcessMaterial(vec3 material, vec3 color);
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -249,7 +249,7 @@ float spotLightAttenuation(vec4 lightpos, vec3 spotdir, float lightCosInnerAngle
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
#if defined(SPECULAR) || defined(PBR) // To do: create define for when normal map is present
|
||||
#if defined(NORMALMAP)
|
||||
mat3 cotangent_frame(vec3 n, vec3 p, vec2 uv)
|
||||
{
|
||||
// get edge vectors of the pixel triangle
|
||||
|
@ -299,397 +299,6 @@ vec3 ApplyNormalMap()
|
|||
}
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
// Dynamic light material modes begin
|
||||
//
|
||||
// To do: move each of the following #if blocks needs to its own file
|
||||
//===========================================================================
|
||||
|
||||
#if !defined(NUM_UBO_LIGHTS) && !defined(SHADER_STORAGE_LIGHTS) // Legacy light mode (no lights[] array)
|
||||
|
||||
vec3 ApplyDynLights(vec3 material, vec3 color)
|
||||
{
|
||||
return material * clamp(color + desaturate(uDynLightColor).rgb, 0.0, 1.4);
|
||||
}
|
||||
|
||||
#elif defined(SPECULAR) // Specular light mode
|
||||
|
||||
vec2 lightAttenuation(int i, vec3 normal, vec3 viewdir, float lightcolorA)
|
||||
{
|
||||
vec4 lightpos = lights[i];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
|
||||
if (lightpos.w < lightdistance)
|
||||
return vec2(0.0); // Early out lights touching surface but not this fragment
|
||||
|
||||
float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);
|
||||
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
|
||||
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
|
||||
|
||||
if (lightcolorA < 0.0) // Sign bit is the attenuated light flag
|
||||
attenuation *= clamp(dot(normal, lightdir), 0.0, 1.0);
|
||||
|
||||
if (attenuation > 0.0) // Skip shadow map test if possible
|
||||
attenuation *= shadowAttenuation(lightpos, lightcolorA);
|
||||
|
||||
if (attenuation <= 0.0)
|
||||
return vec2(0.0);
|
||||
|
||||
float glossiness = uSpecularMaterial.x;
|
||||
float specularLevel = uSpecularMaterial.y;
|
||||
|
||||
vec3 halfdir = normalize(viewdir + lightdir);
|
||||
float specAngle = clamp(dot(halfdir, normal), 0.0f, 1.0f);
|
||||
float phExp = glossiness * 4.0f;
|
||||
return vec2(attenuation, attenuation * specularLevel * pow(specAngle, phExp));
|
||||
}
|
||||
|
||||
vec3 ApplyDynLights(vec3 material, vec3 color)
|
||||
{
|
||||
if (uLightIndex >= 0)
|
||||
{
|
||||
vec4 dynlight = uDynLightColor;
|
||||
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
vec3 normal = ApplyNormalMap();
|
||||
vec3 viewdir = normalize(uCameraPos.xyz - pixelpos.xyz);
|
||||
|
||||
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
||||
|
||||
if (lightRange.z > lightRange.x)
|
||||
{
|
||||
// modulated lights
|
||||
for(int i=lightRange.x; i<lightRange.y; i+=4)
|
||||
{
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec2 attenuation = lightAttenuation(i, normal, viewdir, lightcolor.a);
|
||||
dynlight.rgb += lightcolor.rgb * attenuation.x;
|
||||
specular.rgb += lightcolor.rgb * attenuation.y;
|
||||
}
|
||||
|
||||
// subtractive lights
|
||||
for(int i=lightRange.y; i<lightRange.z; i+=4)
|
||||
{
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec2 attenuation = lightAttenuation(i, normal, viewdir, lightcolor.a);
|
||||
dynlight.rgb -= lightcolor.rgb * attenuation.x;
|
||||
specular.rgb -= lightcolor.rgb * attenuation.y;
|
||||
}
|
||||
}
|
||||
|
||||
dynlight.rgb = clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
|
||||
specular.rgb = clamp(desaturate(specular).rgb, 0.0, 1.4);
|
||||
|
||||
vec4 materialSpec = texture(speculartexture, vTexCoord.st);
|
||||
vec3 frag = material * dynlight.rgb + materialSpec.rgb * specular.rgb;
|
||||
|
||||
if (lightRange.w > lightRange.z)
|
||||
{
|
||||
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
|
||||
|
||||
// additive lights
|
||||
for(int i=lightRange.z; i<lightRange.w; i+=4)
|
||||
{
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec2 attenuation = lightAttenuation(i, normal, viewdir, lightcolor.a);
|
||||
addlight.rgb += lightcolor.rgb * attenuation.x;
|
||||
}
|
||||
|
||||
frag = clamp(frag + desaturate(addlight).rgb, 0.0, 1.0);
|
||||
}
|
||||
|
||||
return frag;
|
||||
}
|
||||
else
|
||||
{
|
||||
return material * clamp(color + desaturate(uDynLightColor).rgb, 0.0, 1.4);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(PBR) // Physically-based-rendering light mode
|
||||
|
||||
const float PI = 3.14159265359;
|
||||
|
||||
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;
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
|
||||
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||
{
|
||||
float r = (roughness + 1.0);
|
||||
float k = (r * r) / 8.0;
|
||||
|
||||
float nom = NdotV;
|
||||
float denom = NdotV * (1.0 - k) + k;
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
|
||||
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||
{
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||
return ggx1 * ggx2;
|
||||
}
|
||||
|
||||
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
||||
{
|
||||
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||
}
|
||||
|
||||
vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
|
||||
{
|
||||
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
||||
}
|
||||
|
||||
float quadraticDistanceAttenuation(vec4 lightpos)
|
||||
{
|
||||
float strength = (1.0 + lightpos.w * lightpos.w * 0.25) * 0.5;
|
||||
|
||||
vec3 distVec = lightpos.xyz - pixelpos.xyz;
|
||||
float attenuation = strength / (1.0 + dot(distVec, distVec));
|
||||
if (attenuation <= 1.0 / 256.0) return 0.0;
|
||||
|
||||
return attenuation;
|
||||
}
|
||||
|
||||
vec3 ApplyDynLights(vec3 albedo, vec3 ambientLight)
|
||||
{
|
||||
vec3 worldpos = pixelpos.xyz;
|
||||
|
||||
albedo = pow(albedo, vec3(2.2)); // sRGB to linear
|
||||
ambientLight = pow(ambientLight, vec3(2.2));
|
||||
|
||||
float metallic = texture(metallictexture, vTexCoord.st).r;
|
||||
float roughness = texture(roughnesstexture, vTexCoord.st).r;
|
||||
float ao = texture(aotexture, vTexCoord.st).r;
|
||||
|
||||
vec3 N = ApplyNormalMap();
|
||||
vec3 V = normalize(uCameraPos.xyz - worldpos);
|
||||
|
||||
vec3 F0 = mix(vec3(0.04), albedo, metallic);
|
||||
|
||||
vec3 Lo = uDynLightColor.rgb;
|
||||
|
||||
if (uLightIndex >= 0)
|
||||
{
|
||||
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
||||
if (lightRange.z > lightRange.x)
|
||||
{
|
||||
//
|
||||
// modulated lights
|
||||
//
|
||||
for(int i=lightRange.x; i<lightRange.y; i+=4)
|
||||
{
|
||||
vec4 lightpos = lights[i];
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
vec3 L = normalize(lightpos.xyz - worldpos);
|
||||
vec3 H = normalize(V + L);
|
||||
|
||||
float attenuation = quadraticDistanceAttenuation(lightpos);
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
if (lightcolor.a < 0.0)
|
||||
attenuation *= clamp(dot(N, L), 0.0, 1.0); // Sign bit is the attenuated light flag
|
||||
|
||||
if (attenuation > 0.0)
|
||||
{
|
||||
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
|
||||
|
||||
vec3 radiance = lightcolor.rgb * attenuation;
|
||||
|
||||
// cook-torrance brdf
|
||||
float NDF = DistributionGGX(N, H, roughness);
|
||||
float G = GeometrySmith(N, V, L, roughness);
|
||||
vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
|
||||
|
||||
vec3 kS = F;
|
||||
vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic);
|
||||
|
||||
vec3 nominator = NDF * G * F;
|
||||
float denominator = 4.0 * clamp(dot(N, V), 0.0, 1.0) * clamp(dot(N, L), 0.0, 1.0);
|
||||
vec3 specular = nominator / max(denominator, 0.001);
|
||||
|
||||
Lo += (kD * albedo / PI + specular) * radiance;
|
||||
}
|
||||
}
|
||||
//
|
||||
// subtractive lights
|
||||
//
|
||||
for(int i=lightRange.y; i<lightRange.z; i+=4)
|
||||
{
|
||||
vec4 lightpos = lights[i];
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
vec3 L = normalize(lightpos.xyz - worldpos);
|
||||
vec3 H = normalize(V + L);
|
||||
|
||||
float attenuation = quadraticDistanceAttenuation(lightpos);
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
if (lightcolor.a < 0.0)
|
||||
attenuation *= clamp(dot(N, L), 0.0, 1.0); // Sign bit is the attenuated light flag
|
||||
|
||||
if (attenuation > 0.0)
|
||||
{
|
||||
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
|
||||
|
||||
vec3 radiance = lightcolor.rgb * attenuation;
|
||||
|
||||
// cook-torrance brdf
|
||||
float NDF = DistributionGGX(N, H, roughness);
|
||||
float G = GeometrySmith(N, V, L, roughness);
|
||||
vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
|
||||
|
||||
vec3 kS = F;
|
||||
vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic);
|
||||
|
||||
vec3 nominator = NDF * G * F;
|
||||
float denominator = 4.0 * clamp(dot(N, V), 0.0, 1.0) * clamp(dot(N, L), 0.0, 1.0);
|
||||
vec3 specular = nominator / max(denominator, 0.001);
|
||||
|
||||
Lo -= (kD * albedo / PI + specular) * radiance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pretend we sampled the sector light level from an irradiance map
|
||||
|
||||
vec3 F = fresnelSchlickRoughness(clamp(dot(N, V), 0.0, 1.0), F0, roughness);
|
||||
|
||||
vec3 kS = F;
|
||||
vec3 kD = 1.0 - kS;
|
||||
|
||||
vec3 irradiance = ambientLight; // texture(irradianceMap, N).rgb
|
||||
vec3 diffuse = irradiance * albedo;
|
||||
|
||||
//kD *= 1.0 - metallic;
|
||||
//const float MAX_REFLECTION_LOD = 4.0;
|
||||
//vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * MAX_REFLECTION_LOD).rgb;
|
||||
//vec2 envBRDF = texture(brdfLUT, vec2(clamp(dot(N, V), 0.0, 1.0), roughness)).rg;
|
||||
//vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y);
|
||||
|
||||
//vec3 ambient = (kD * diffuse + specular) * ao;
|
||||
vec3 ambient = (kD * diffuse) * ao;
|
||||
|
||||
vec3 color = ambient + Lo;
|
||||
|
||||
// Tonemap (reinhard) and apply sRGB gamma
|
||||
//color = color / (color + vec3(1.0));
|
||||
return pow(color, vec3(1.0 / 2.2));
|
||||
}
|
||||
|
||||
#else // Normal dynlight mode
|
||||
|
||||
vec3 lightContribution(int i, vec3 normal)
|
||||
{
|
||||
vec4 lightpos = lights[i];
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
|
||||
if (lightpos.w < lightdistance)
|
||||
return vec3(0.0); // Early out lights touching surface but not this fragment
|
||||
|
||||
float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);
|
||||
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
|
||||
if (lightcolor.a < 0.0) // Sign bit is the attenuated light flag
|
||||
{
|
||||
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
|
||||
attenuation *= clamp(dot(normal, lightdir), 0.0, 1.0);
|
||||
}
|
||||
|
||||
if (attenuation > 0.0) // Skip shadow map test if possible
|
||||
{
|
||||
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
|
||||
return lightcolor.rgb * attenuation;
|
||||
}
|
||||
else
|
||||
{
|
||||
return vec3(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 ApplyDynLights(vec3 material, vec3 color)
|
||||
{
|
||||
if (uLightIndex >= 0)
|
||||
{
|
||||
vec4 dynlight = uDynLightColor;
|
||||
vec3 normal = ApplyNormalMap();
|
||||
|
||||
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
||||
|
||||
if (lightRange.z > lightRange.x)
|
||||
{
|
||||
// modulated lights
|
||||
for(int i=lightRange.x; i<lightRange.y; i+=4)
|
||||
{
|
||||
dynlight.rgb += lightContribution(i, normal);
|
||||
}
|
||||
|
||||
// subtractive lights
|
||||
for(int i=lightRange.y; i<lightRange.z; i+=4)
|
||||
{
|
||||
dynlight.rgb -= lightContribution(i, normal);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 frag = material * clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
|
||||
|
||||
if (lightRange.w > lightRange.z)
|
||||
{
|
||||
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
|
||||
|
||||
// additive lights
|
||||
for(int i=lightRange.z; i<lightRange.w; i+=4)
|
||||
{
|
||||
addlight.rgb += lightContribution(i, normal);
|
||||
}
|
||||
|
||||
frag = clamp(frag + desaturate(addlight).rgb, 0.0, 1.0);
|
||||
}
|
||||
|
||||
return frag;
|
||||
}
|
||||
else
|
||||
{
|
||||
return material * clamp(color + desaturate(uDynLightColor).rgb, 0.0, 1.4);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
// Dynamic light material modes end
|
||||
//===========================================================================
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Calculate light
|
||||
|
@ -748,7 +357,7 @@ vec4 getLightColor(vec4 material, float fogdist, float fogfactor)
|
|||
//
|
||||
// apply dynamic lights
|
||||
//
|
||||
return vec4(ApplyDynLights(material.rgb, color.rgb), material.a * vColor.a);
|
||||
return vec4(ProcessMaterial(material.rgb, color.rgb), material.a * vColor.a);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
5
wadsrc/static/shaders/glsl/material_nolight.fp
Normal file
5
wadsrc/static/shaders/glsl/material_nolight.fp
Normal file
|
@ -0,0 +1,5 @@
|
|||
|
||||
vec3 ProcessMaterial(vec3 material, vec3 color)
|
||||
{
|
||||
return material * clamp(color + desaturate(uDynLightColor).rgb, 0.0, 1.4);
|
||||
}
|
80
wadsrc/static/shaders/glsl/material_normal.fp
Normal file
80
wadsrc/static/shaders/glsl/material_normal.fp
Normal file
|
@ -0,0 +1,80 @@
|
|||
|
||||
vec3 lightContribution(int i, vec3 normal)
|
||||
{
|
||||
vec4 lightpos = lights[i];
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
|
||||
if (lightpos.w < lightdistance)
|
||||
return vec3(0.0); // Early out lights touching surface but not this fragment
|
||||
|
||||
float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);
|
||||
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
|
||||
if (lightcolor.a < 0.0) // Sign bit is the attenuated light flag
|
||||
{
|
||||
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
|
||||
attenuation *= clamp(dot(normal, lightdir), 0.0, 1.0);
|
||||
}
|
||||
|
||||
if (attenuation > 0.0) // Skip shadow map test if possible
|
||||
{
|
||||
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
|
||||
return lightcolor.rgb * attenuation;
|
||||
}
|
||||
else
|
||||
{
|
||||
return vec3(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 ProcessMaterial(vec3 material, vec3 color)
|
||||
{
|
||||
if (uLightIndex >= 0)
|
||||
{
|
||||
vec4 dynlight = uDynLightColor;
|
||||
vec3 normal = ApplyNormalMap();
|
||||
|
||||
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
||||
|
||||
if (lightRange.z > lightRange.x)
|
||||
{
|
||||
// modulated lights
|
||||
for(int i=lightRange.x; i<lightRange.y; i+=4)
|
||||
{
|
||||
dynlight.rgb += lightContribution(i, normal);
|
||||
}
|
||||
|
||||
// subtractive lights
|
||||
for(int i=lightRange.y; i<lightRange.z; i+=4)
|
||||
{
|
||||
dynlight.rgb -= lightContribution(i, normal);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 frag = material * clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
|
||||
|
||||
if (lightRange.w > lightRange.z)
|
||||
{
|
||||
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
|
||||
|
||||
// additive lights
|
||||
for(int i=lightRange.z; i<lightRange.w; i+=4)
|
||||
{
|
||||
addlight.rgb += lightContribution(i, normal);
|
||||
}
|
||||
|
||||
frag = clamp(frag + desaturate(addlight).rgb, 0.0, 1.0);
|
||||
}
|
||||
|
||||
return frag;
|
||||
}
|
||||
else
|
||||
{
|
||||
return material * clamp(color + desaturate(uDynLightColor).rgb, 0.0, 1.4);
|
||||
}
|
||||
}
|
189
wadsrc/static/shaders/glsl/material_pbr.fp
Normal file
189
wadsrc/static/shaders/glsl/material_pbr.fp
Normal file
|
@ -0,0 +1,189 @@
|
|||
|
||||
const float PI = 3.14159265359;
|
||||
|
||||
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;
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
|
||||
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||
{
|
||||
float r = (roughness + 1.0);
|
||||
float k = (r * r) / 8.0;
|
||||
|
||||
float nom = NdotV;
|
||||
float denom = NdotV * (1.0 - k) + k;
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
|
||||
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||
{
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||
return ggx1 * ggx2;
|
||||
}
|
||||
|
||||
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
||||
{
|
||||
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||
}
|
||||
|
||||
vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
|
||||
{
|
||||
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
||||
}
|
||||
|
||||
float quadraticDistanceAttenuation(vec4 lightpos)
|
||||
{
|
||||
float strength = (1.0 + lightpos.w * lightpos.w * 0.25) * 0.5;
|
||||
|
||||
vec3 distVec = lightpos.xyz - pixelpos.xyz;
|
||||
float attenuation = strength / (1.0 + dot(distVec, distVec));
|
||||
if (attenuation <= 1.0 / 256.0) return 0.0;
|
||||
|
||||
return attenuation;
|
||||
}
|
||||
|
||||
vec3 ProcessMaterial(vec3 albedo, vec3 ambientLight)
|
||||
{
|
||||
vec3 worldpos = pixelpos.xyz;
|
||||
|
||||
albedo = pow(albedo, vec3(2.2)); // sRGB to linear
|
||||
ambientLight = pow(ambientLight, vec3(2.2));
|
||||
|
||||
float metallic = texture(metallictexture, vTexCoord.st).r;
|
||||
float roughness = texture(roughnesstexture, vTexCoord.st).r;
|
||||
float ao = texture(aotexture, vTexCoord.st).r;
|
||||
|
||||
vec3 N = ApplyNormalMap();
|
||||
vec3 V = normalize(uCameraPos.xyz - worldpos);
|
||||
|
||||
vec3 F0 = mix(vec3(0.04), albedo, metallic);
|
||||
|
||||
vec3 Lo = uDynLightColor.rgb;
|
||||
|
||||
if (uLightIndex >= 0)
|
||||
{
|
||||
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
||||
if (lightRange.z > lightRange.x)
|
||||
{
|
||||
//
|
||||
// modulated lights
|
||||
//
|
||||
for(int i=lightRange.x; i<lightRange.y; i+=4)
|
||||
{
|
||||
vec4 lightpos = lights[i];
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
vec3 L = normalize(lightpos.xyz - worldpos);
|
||||
vec3 H = normalize(V + L);
|
||||
|
||||
float attenuation = quadraticDistanceAttenuation(lightpos);
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
if (lightcolor.a < 0.0)
|
||||
attenuation *= clamp(dot(N, L), 0.0, 1.0); // Sign bit is the attenuated light flag
|
||||
|
||||
if (attenuation > 0.0)
|
||||
{
|
||||
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
|
||||
|
||||
vec3 radiance = lightcolor.rgb * attenuation;
|
||||
|
||||
// cook-torrance brdf
|
||||
float NDF = DistributionGGX(N, H, roughness);
|
||||
float G = GeometrySmith(N, V, L, roughness);
|
||||
vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
|
||||
|
||||
vec3 kS = F;
|
||||
vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic);
|
||||
|
||||
vec3 nominator = NDF * G * F;
|
||||
float denominator = 4.0 * clamp(dot(N, V), 0.0, 1.0) * clamp(dot(N, L), 0.0, 1.0);
|
||||
vec3 specular = nominator / max(denominator, 0.001);
|
||||
|
||||
Lo += (kD * albedo / PI + specular) * radiance;
|
||||
}
|
||||
}
|
||||
//
|
||||
// subtractive lights
|
||||
//
|
||||
for(int i=lightRange.y; i<lightRange.z; i+=4)
|
||||
{
|
||||
vec4 lightpos = lights[i];
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
vec3 L = normalize(lightpos.xyz - worldpos);
|
||||
vec3 H = normalize(V + L);
|
||||
|
||||
float attenuation = quadraticDistanceAttenuation(lightpos);
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
if (lightcolor.a < 0.0)
|
||||
attenuation *= clamp(dot(N, L), 0.0, 1.0); // Sign bit is the attenuated light flag
|
||||
|
||||
if (attenuation > 0.0)
|
||||
{
|
||||
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
|
||||
|
||||
vec3 radiance = lightcolor.rgb * attenuation;
|
||||
|
||||
// cook-torrance brdf
|
||||
float NDF = DistributionGGX(N, H, roughness);
|
||||
float G = GeometrySmith(N, V, L, roughness);
|
||||
vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
|
||||
|
||||
vec3 kS = F;
|
||||
vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic);
|
||||
|
||||
vec3 nominator = NDF * G * F;
|
||||
float denominator = 4.0 * clamp(dot(N, V), 0.0, 1.0) * clamp(dot(N, L), 0.0, 1.0);
|
||||
vec3 specular = nominator / max(denominator, 0.001);
|
||||
|
||||
Lo -= (kD * albedo / PI + specular) * radiance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pretend we sampled the sector light level from an irradiance map
|
||||
|
||||
vec3 F = fresnelSchlickRoughness(clamp(dot(N, V), 0.0, 1.0), F0, roughness);
|
||||
|
||||
vec3 kS = F;
|
||||
vec3 kD = 1.0 - kS;
|
||||
|
||||
vec3 irradiance = ambientLight; // texture(irradianceMap, N).rgb
|
||||
vec3 diffuse = irradiance * albedo;
|
||||
|
||||
//kD *= 1.0 - metallic;
|
||||
//const float MAX_REFLECTION_LOD = 4.0;
|
||||
//vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * MAX_REFLECTION_LOD).rgb;
|
||||
//vec2 envBRDF = texture(brdfLUT, vec2(clamp(dot(N, V), 0.0, 1.0), roughness)).rg;
|
||||
//vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y);
|
||||
|
||||
//vec3 ambient = (kD * diffuse + specular) * ao;
|
||||
vec3 ambient = (kD * diffuse) * ao;
|
||||
|
||||
vec3 color = ambient + Lo;
|
||||
|
||||
// Tonemap (reinhard) and apply sRGB gamma
|
||||
//color = color / (color + vec3(1.0));
|
||||
return pow(color, vec3(1.0 / 2.2));
|
||||
}
|
97
wadsrc/static/shaders/glsl/material_specular.fp
Normal file
97
wadsrc/static/shaders/glsl/material_specular.fp
Normal file
|
@ -0,0 +1,97 @@
|
|||
|
||||
vec2 lightAttenuation(int i, vec3 normal, vec3 viewdir, float lightcolorA)
|
||||
{
|
||||
vec4 lightpos = lights[i];
|
||||
vec4 lightspot1 = lights[i+2];
|
||||
vec4 lightspot2 = lights[i+3];
|
||||
|
||||
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
|
||||
if (lightpos.w < lightdistance)
|
||||
return vec2(0.0); // Early out lights touching surface but not this fragment
|
||||
|
||||
float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);
|
||||
|
||||
if (lightspot1.w == 1.0)
|
||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||
|
||||
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
|
||||
|
||||
if (lightcolorA < 0.0) // Sign bit is the attenuated light flag
|
||||
attenuation *= clamp(dot(normal, lightdir), 0.0, 1.0);
|
||||
|
||||
if (attenuation > 0.0) // Skip shadow map test if possible
|
||||
attenuation *= shadowAttenuation(lightpos, lightcolorA);
|
||||
|
||||
if (attenuation <= 0.0)
|
||||
return vec2(0.0);
|
||||
|
||||
float glossiness = uSpecularMaterial.x;
|
||||
float specularLevel = uSpecularMaterial.y;
|
||||
|
||||
vec3 halfdir = normalize(viewdir + lightdir);
|
||||
float specAngle = clamp(dot(halfdir, normal), 0.0f, 1.0f);
|
||||
float phExp = glossiness * 4.0f;
|
||||
return vec2(attenuation, attenuation * specularLevel * pow(specAngle, phExp));
|
||||
}
|
||||
|
||||
vec3 ProcessMaterial(vec3 material, vec3 color)
|
||||
{
|
||||
if (uLightIndex >= 0)
|
||||
{
|
||||
vec4 dynlight = uDynLightColor;
|
||||
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
vec3 normal = ApplyNormalMap();
|
||||
vec3 viewdir = normalize(uCameraPos.xyz - pixelpos.xyz);
|
||||
|
||||
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
||||
|
||||
if (lightRange.z > lightRange.x)
|
||||
{
|
||||
// modulated lights
|
||||
for(int i=lightRange.x; i<lightRange.y; i+=4)
|
||||
{
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec2 attenuation = lightAttenuation(i, normal, viewdir, lightcolor.a);
|
||||
dynlight.rgb += lightcolor.rgb * attenuation.x;
|
||||
specular.rgb += lightcolor.rgb * attenuation.y;
|
||||
}
|
||||
|
||||
// subtractive lights
|
||||
for(int i=lightRange.y; i<lightRange.z; i+=4)
|
||||
{
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec2 attenuation = lightAttenuation(i, normal, viewdir, lightcolor.a);
|
||||
dynlight.rgb -= lightcolor.rgb * attenuation.x;
|
||||
specular.rgb -= lightcolor.rgb * attenuation.y;
|
||||
}
|
||||
}
|
||||
|
||||
dynlight.rgb = clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
|
||||
specular.rgb = clamp(desaturate(specular).rgb, 0.0, 1.4);
|
||||
|
||||
vec4 materialSpec = texture(speculartexture, vTexCoord.st);
|
||||
vec3 frag = material * dynlight.rgb + materialSpec.rgb * specular.rgb;
|
||||
|
||||
if (lightRange.w > lightRange.z)
|
||||
{
|
||||
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
|
||||
|
||||
// additive lights
|
||||
for(int i=lightRange.z; i<lightRange.w; i+=4)
|
||||
{
|
||||
vec4 lightcolor = lights[i+1];
|
||||
vec2 attenuation = lightAttenuation(i, normal, viewdir, lightcolor.a);
|
||||
addlight.rgb += lightcolor.rgb * attenuation.x;
|
||||
}
|
||||
|
||||
frag = clamp(frag + desaturate(addlight).rgb, 0.0, 1.0);
|
||||
}
|
||||
|
||||
return frag;
|
||||
}
|
||||
else
|
||||
{
|
||||
return material * clamp(color + desaturate(uDynLightColor).rgb, 0.0, 1.4);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue