mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-25 05:31:00 +00:00
- Add specular and normal map handling to main.fp
This commit is contained in:
parent
e045fb57c9
commit
81c6808d2a
2 changed files with 137 additions and 29 deletions
|
@ -468,13 +468,37 @@ FMaterial::FMaterial(FTexture * tx, bool expanded)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (tx->gl_info.Normal && tx->gl_info.Specular)
|
||||||
|
{
|
||||||
|
for (auto &texture : { tx->gl_info.Normal, tx->gl_info.Specular })
|
||||||
|
{
|
||||||
|
ValidateSysTexture(texture, expanded);
|
||||||
|
mTextureLayers.Push({ texture, false });
|
||||||
|
}
|
||||||
|
mShaderIndex = SHADER_Specular;
|
||||||
|
}
|
||||||
|
else if (tx->gl_info.Normal && tx->gl_info.Metallic && tx->gl_info.Roughness && tx->gl_info.AmbientOcclusion)
|
||||||
|
{
|
||||||
|
for (auto &texture : { tx->gl_info.Normal, tx->gl_info.Metallic, tx->gl_info.Roughness, tx->gl_info.AmbientOcclusion })
|
||||||
|
{
|
||||||
|
ValidateSysTexture(texture, expanded);
|
||||||
|
mTextureLayers.Push({ texture, false });
|
||||||
|
}
|
||||||
|
mShaderIndex = SHADER_PBR;
|
||||||
|
}
|
||||||
|
|
||||||
tx->CreateDefaultBrightmap();
|
tx->CreateDefaultBrightmap();
|
||||||
if (tx->gl_info.Brightmap != NULL)
|
if (tx->gl_info.Brightmap != NULL)
|
||||||
{
|
{
|
||||||
ValidateSysTexture(tx->gl_info.Brightmap, expanded);
|
ValidateSysTexture(tx->gl_info.Brightmap, expanded);
|
||||||
FTextureLayer layer = {tx->gl_info.Brightmap, false};
|
FTextureLayer layer = {tx->gl_info.Brightmap, false};
|
||||||
mTextureLayers.Push(layer);
|
mTextureLayers.Push(layer);
|
||||||
mShaderIndex = SHADER_Brightmap;
|
if (mShaderIndex == SHADER_Specular)
|
||||||
|
mShaderIndex = SHADER_SpecularBrightmap;
|
||||||
|
else if (mShaderIndex == SHADER_PBR)
|
||||||
|
mShaderIndex = SHADER_PBRBrightmap;
|
||||||
|
else
|
||||||
|
mShaderIndex = SHADER_Brightmap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -268,29 +268,112 @@ float diffuseContribution(vec3 lightDirection, vec3 normal)
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// Calculates the brightness of a dynamic point light
|
// Blinn specular light calculation
|
||||||
// Todo: Find a better way to define which lighting model to use.
|
|
||||||
// (Specular mode has been removed for now.)
|
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
float pointLightAttenuation(vec4 lightpos, float lightcolorA)
|
float blinnSpecularContribution(float diffuseContribution, vec3 lightDirection, vec3 faceNormal, float glossiness, float specularLevel)
|
||||||
|
{
|
||||||
|
if (diffuseContribution > 0.0f)
|
||||||
|
{
|
||||||
|
vec3 viewDir = normalize(uCameraPos.xyz - pixelpos.xyz);
|
||||||
|
vec3 halfDir = normalize(lightDirection + viewDir);
|
||||||
|
float specAngle = max(dot(halfDir, faceNormal), 0.0f);
|
||||||
|
float phExp = glossiness * 4.0f;
|
||||||
|
return specularLevel * pow(specAngle, phExp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Adjust normal vector according to the normal map
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
#if defined(SPECULAR) || defined(PBR)
|
||||||
|
mat3 cotangent_frame(vec3 n, vec3 p, vec2 uv)
|
||||||
|
{
|
||||||
|
// get edge vectors of the pixel triangle
|
||||||
|
vec3 dp1 = dFdx(p);
|
||||||
|
vec3 dp2 = dFdy(p);
|
||||||
|
vec2 duv1 = dFdx(uv);
|
||||||
|
vec2 duv2 = dFdy(uv);
|
||||||
|
|
||||||
|
// solve the linear system
|
||||||
|
vec3 dp2perp = cross(n, dp2); // cross(dp2, n);
|
||||||
|
vec3 dp1perp = cross(dp1, n); // cross(n, dp1);
|
||||||
|
vec3 t = dp2perp * duv1.x + dp1perp * duv2.x;
|
||||||
|
vec3 b = dp2perp * duv1.y + dp1perp * duv2.y;
|
||||||
|
|
||||||
|
// construct a scale-invariant frame
|
||||||
|
float invmax = inversesqrt(max(dot(t,t), dot(b,b)));
|
||||||
|
return mat3(t * invmax, b * invmax, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ApplyNormalMap()
|
||||||
|
{
|
||||||
|
#define WITH_NORMALMAP_UNSIGNED
|
||||||
|
#define WITH_NORMALMAP_GREEN_UP
|
||||||
|
//#define WITH_NORMALMAP_2CHANNEL
|
||||||
|
|
||||||
|
vec3 interpolatedNormal = normalize(gl_FrontFacing ? -vWorldNormal.xyz : vWorldNormal.xyz);
|
||||||
|
|
||||||
|
vec3 map = texture(normaltexture, vTexCoord.st).xyz;
|
||||||
|
#if defined(WITH_NORMALMAP_UNSIGNED)
|
||||||
|
map = map * 255./127. - 128./127.; // Math so "odd" because 0.5 cannot be precisely described in an unsigned format
|
||||||
|
#endif
|
||||||
|
#if defined(WITH_NORMALMAP_2CHANNEL)
|
||||||
|
map.z = sqrt(1 - dot(map.xy, map.xy));
|
||||||
|
#endif
|
||||||
|
#if defined(WITH_NORMALMAP_GREEN_UP)
|
||||||
|
map.y = -map.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mat3 tbn = cotangent_frame(interpolatedNormal, pixelpos.xyz, vTexCoord.st);
|
||||||
|
vec3 bumpedNormal = normalize(tbn * map);
|
||||||
|
return bumpedNormal;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
vec3 ApplyNormalMap()
|
||||||
|
{
|
||||||
|
return normalize(vWorldNormal.xyz);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Calculates the brightness of a dynamic point light
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
vec2 pointLightAttenuation(vec4 lightpos, float lightcolorA)
|
||||||
{
|
{
|
||||||
float attenuation = max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
|
float attenuation = max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
|
||||||
if (attenuation == 0.0) return 0.0;
|
if (attenuation == 0.0) return vec2(0.0);
|
||||||
#ifdef SUPPORTS_SHADOWMAPS
|
#ifdef SUPPORTS_SHADOWMAPS
|
||||||
float shadowIndex = abs(lightcolorA) - 1.0;
|
float shadowIndex = abs(lightcolorA) - 1.0;
|
||||||
attenuation *= shadowmapAttenuation(lightpos, shadowIndex);
|
attenuation *= shadowmapAttenuation(lightpos, shadowIndex);
|
||||||
#endif
|
#endif
|
||||||
if (lightcolorA >= 0.0) // Sign bit is the attenuated light flag
|
if (lightcolorA >= 0.0) // Sign bit is the attenuated light flag
|
||||||
{
|
{
|
||||||
return attenuation;
|
return vec2(attenuation, 0.0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vec3 lightDirection = normalize(lightpos.xyz - pixelpos.xyz);
|
vec3 lightDirection = normalize(lightpos.xyz - pixelpos.xyz);
|
||||||
float diffuseAmount = diffuseContribution(lightDirection, normalize(vWorldNormal.xyz));
|
vec3 pixelnormal = ApplyNormalMap();
|
||||||
return attenuation * diffuseAmount;
|
float diffuseAmount = diffuseContribution(lightDirection, pixelnormal);
|
||||||
|
|
||||||
|
#if defined(SPECULAR)
|
||||||
|
float specularAmount = blinnSpecularContribution(diffuseAmount, lightDirection, pixelnormal, 10.0, 0.12);
|
||||||
|
return vec2(diffuseAmount, specularAmount) * attenuation;
|
||||||
|
#else
|
||||||
|
return vec2(attenuation * diffuseAmount, 0.0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +398,7 @@ float spotLightAttenuation(vec4 lightpos, vec3 spotdir, float lightCosInnerAngle
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
vec4 getLightColor(float fogdist, float fogfactor)
|
vec4 getLightColor(vec4 material, vec4 materialSpec, float fogdist, float fogfactor)
|
||||||
{
|
{
|
||||||
vec4 color = vColor;
|
vec4 color = vColor;
|
||||||
|
|
||||||
|
@ -361,6 +444,7 @@ vec4 getLightColor(float fogdist, float fogfactor)
|
||||||
//
|
//
|
||||||
|
|
||||||
vec4 dynlight = uDynLightColor;
|
vec4 dynlight = uDynLightColor;
|
||||||
|
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
#if defined NUM_UBO_LIGHTS || defined SHADER_STORAGE_LIGHTS
|
#if defined NUM_UBO_LIGHTS || defined SHADER_STORAGE_LIGHTS
|
||||||
if (uLightIndex >= 0)
|
if (uLightIndex >= 0)
|
||||||
|
@ -378,11 +462,11 @@ vec4 getLightColor(float fogdist, float fogfactor)
|
||||||
vec4 lightspot1 = lights[i+2];
|
vec4 lightspot1 = lights[i+2];
|
||||||
vec4 lightspot2 = lights[i+3];
|
vec4 lightspot2 = lights[i+3];
|
||||||
|
|
||||||
float attenuation = pointLightAttenuation(lightpos, lightcolor.a);
|
vec2 attenuation = pointLightAttenuation(lightpos, lightcolor.a);
|
||||||
if (lightspot1.w == 1.0)
|
if (lightspot1.w == 1.0)
|
||||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
attenuation.xy *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||||
lightcolor.rgb *= attenuation;
|
dynlight.rgb += lightcolor.rgb * attenuation.x;
|
||||||
dynlight.rgb += lightcolor.rgb;
|
specular.rgb += lightcolor.rgb * attenuation.y;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// subtractive lights
|
// subtractive lights
|
||||||
|
@ -394,19 +478,20 @@ vec4 getLightColor(float fogdist, float fogfactor)
|
||||||
vec4 lightspot1 = lights[i+2];
|
vec4 lightspot1 = lights[i+2];
|
||||||
vec4 lightspot2 = lights[i+3];
|
vec4 lightspot2 = lights[i+3];
|
||||||
|
|
||||||
float attenuation = pointLightAttenuation(lightpos, lightcolor.a);
|
vec2 attenuation = pointLightAttenuation(lightpos, lightcolor.a);
|
||||||
if (lightspot1.w == 1.0)
|
if (lightspot1.w == 1.0)
|
||||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
attenuation.xy *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||||
lightcolor.rgb *= attenuation;
|
dynlight.rgb -= lightcolor.rgb * attenuation.x;
|
||||||
dynlight.rgb -= lightcolor.rgb;
|
specular.rgb -= lightcolor.rgb * attenuation.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
color.rgb = clamp(color.rgb + desaturate(dynlight).rgb, 0.0, 1.4);
|
color.rgb = clamp(color.rgb + desaturate(dynlight).rgb, 0.0, 1.4);
|
||||||
|
specular.rgb = clamp(specular.rgb + desaturate(specular).rgb, 0.0, 1.4);
|
||||||
|
|
||||||
// prevent any unintentional messing around with the alpha.
|
// prevent any unintentional messing around with the alpha.
|
||||||
return vec4(color.rgb, vColor.a);
|
return vec4(material.rgb * color.rgb + materialSpec.rgb * specular.rgb, material.a * vColor.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -457,12 +542,6 @@ void main()
|
||||||
{
|
{
|
||||||
vec4 frag = ProcessTexel();
|
vec4 frag = ProcessTexel();
|
||||||
|
|
||||||
#if defined(SPECULAR)
|
|
||||||
frag = texture(speculartexture, vTexCoord.st);
|
|
||||||
#elif defined(PBR)
|
|
||||||
frag = texture(metallictexture, vTexCoord.st);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NO_ALPHATEST
|
#ifndef NO_ALPHATEST
|
||||||
if (frag.a <= uAlphaThreshold) discard;
|
if (frag.a <= uAlphaThreshold) discard;
|
||||||
#endif
|
#endif
|
||||||
|
@ -492,8 +571,13 @@ void main()
|
||||||
fogfactor = exp2 (uFogDensity * fogdist);
|
fogfactor = exp2 (uFogDensity * fogdist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(SPECULAR)
|
||||||
frag *= getLightColor(fogdist, fogfactor);
|
vec4 materialSpec = texture(speculartexture, vTexCoord.st);
|
||||||
|
#else
|
||||||
|
vec4 materialSpec = vec4(0.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
frag = getLightColor(frag, materialSpec, fogdist, fogfactor);
|
||||||
|
|
||||||
#if defined NUM_UBO_LIGHTS || defined SHADER_STORAGE_LIGHTS
|
#if defined NUM_UBO_LIGHTS || defined SHADER_STORAGE_LIGHTS
|
||||||
if (uLightIndex >= 0)
|
if (uLightIndex >= 0)
|
||||||
|
@ -513,7 +597,7 @@ void main()
|
||||||
vec4 lightspot1 = lights[i+2];
|
vec4 lightspot1 = lights[i+2];
|
||||||
vec4 lightspot2 = lights[i+3];
|
vec4 lightspot2 = lights[i+3];
|
||||||
|
|
||||||
float attenuation = pointLightAttenuation(lightpos, lightcolor.a);
|
float attenuation = pointLightAttenuation(lightpos, lightcolor.a).x;
|
||||||
if (lightspot1.w == 1.0)
|
if (lightspot1.w == 1.0)
|
||||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||||
lightcolor.rgb *= attenuation;
|
lightcolor.rgb *= attenuation;
|
||||||
|
|
Loading…
Reference in a new issue