Refactor Blinn-Phong shaders

This commit is contained in:
Vsevolod Kremianskii 2021-05-08 00:05:34 +07:00
parent e6b70fe6e2
commit 0e22dbfd47
6 changed files with 146 additions and 148 deletions

View file

@ -38,6 +38,7 @@ namespace graphics {
extern char g_shaderBaseHeader[];
extern char g_shaderBaseModel[];
extern char g_shaderBaseBlinnPhong[];
extern char g_shaderBasePBR[];
extern char g_shaderBasePBRIBL[];
extern char g_shaderVertexSimple[];
@ -56,7 +57,7 @@ extern char g_shaderFragmentGrass[];
extern char g_shaderFragmentBlur[];
extern char g_shaderFragmentPresentWorld[];
extern char g_shaderFragmentBlinnPhong[];
extern char g_shaderFragmentBlinnPhongTextureless[];
extern char g_shaderFragmentBlinnPhongDiffuseless[];
extern char g_shaderFragmentIrradiance[];
extern char g_shaderFragmentPrefilter[];
extern char g_shaderFragmentBRDF[];
@ -93,8 +94,8 @@ void Shaders::init() {
initShader(ShaderName::FragmentGrass, GL_FRAGMENT_SHADER, { g_shaderBaseHeader, g_shaderFragmentGrass });
initShader(ShaderName::FragmentBlur, GL_FRAGMENT_SHADER, { g_shaderBaseHeader, g_shaderFragmentBlur });
initShader(ShaderName::FragmentPresentWorld, GL_FRAGMENT_SHADER, { g_shaderBaseHeader, g_shaderFragmentPresentWorld });
initShader(ShaderName::FragmentBlinnPhong, GL_FRAGMENT_SHADER, { g_shaderBaseHeader, g_shaderBaseModel, g_shaderFragmentBlinnPhong });
initShader(ShaderName::FragmentBlinnPhongTextureless, GL_FRAGMENT_SHADER, { g_shaderBaseHeader, g_shaderBaseModel, g_shaderFragmentBlinnPhongTextureless });
initShader(ShaderName::FragmentBlinnPhong, GL_FRAGMENT_SHADER, { g_shaderBaseHeader, g_shaderBaseModel, g_shaderBaseBlinnPhong, g_shaderFragmentBlinnPhong });
initShader(ShaderName::FragmentBlinnPhongDiffuseless, GL_FRAGMENT_SHADER, { g_shaderBaseHeader, g_shaderBaseModel, g_shaderBaseBlinnPhong, g_shaderFragmentBlinnPhongDiffuseless });
initShader(ShaderName::FragmentIrradiance, GL_FRAGMENT_SHADER, { g_shaderBaseHeader, g_shaderFragmentIrradiance });
initShader(ShaderName::FragmentPrefilter, GL_FRAGMENT_SHADER, { g_shaderBaseHeader, g_shaderBasePBR, g_shaderBasePBRIBL, g_shaderFragmentPrefilter });
initShader(ShaderName::FragmentBRDF, GL_FRAGMENT_SHADER, { g_shaderBaseHeader, g_shaderBasePBR, g_shaderBasePBRIBL, g_shaderFragmentBRDF });
@ -110,7 +111,7 @@ void Shaders::init() {
initProgram(ShaderProgram::SimplePresentWorld, { ShaderName::VertexSimple, ShaderName::FragmentPresentWorld });
initProgram(ShaderProgram::ModelColor, { ShaderName::VertexModel, ShaderName::FragmentColor });
initProgram(ShaderProgram::ModelBlinnPhong, { ShaderName::VertexModel, ShaderName::FragmentBlinnPhong });
initProgram(ShaderProgram::ModelBlinnPhongTextureless, { ShaderName::VertexModel, ShaderName::FragmentBlinnPhongTextureless });
initProgram(ShaderProgram::ModelBlinnPhongDiffuseless, { ShaderName::VertexModel, ShaderName::FragmentBlinnPhongDiffuseless });
initProgram(ShaderProgram::ModelPBR, { ShaderName::VertexModel, ShaderName::FragmentPBR });
initProgram(ShaderProgram::ParticleParticle, { ShaderName::VertexParticle, ShaderName::FragmentParticle });
initProgram(ShaderProgram::GrassGrass, { ShaderName::VertexGrass, ShaderName::FragmentGrass });

View file

@ -46,7 +46,7 @@ enum class ShaderProgram {
SimplePresentWorld,
ModelColor,
ModelBlinnPhong,
ModelBlinnPhongTextureless,
ModelBlinnPhongDiffuseless,
ModelPBR,
ParticleParticle,
GrassGrass,
@ -244,7 +244,7 @@ private:
// Blinn-Phong
FragmentBlinnPhong,
FragmentBlinnPhongTextureless,
FragmentBlinnPhongDiffuseless,
// PBR
FragmentIrradiance,

View file

@ -202,6 +202,10 @@ in mat3 fragTanSpace;
layout(location = 0) out vec4 fragColor;
layout(location = 1) out vec4 fragColorBright;
vec2 getUV() {
return fragTexCoords + uGeneral.uvOffset;
}
vec2 packUV(vec2 uv, vec4 bounds) {
return bounds.xy + bounds.zw * clamp(fract(uv), 0.001, 0.999);
}
@ -240,14 +244,26 @@ vec3 getNormalFromBumpmap(vec2 uv) {
}
result = normalize(fragTanSpace * result);
return result;
}
vec3 getNormal(vec2 uv) {
vec3 result;
if (isFeatureEnabled(FEATURE_BUMPMAPS)) {
result = getNormalFromBumpmap(uv);
} else {
result = normalize(fragNormal);
}
return result;
}
float getShadow() {
float shadow = 0.0;
if (!isFeatureEnabled(FEATURE_SHADOWS) || !uShadows.lightPresent) return 0.0;
float result = 0.0;
if (uShadows.lightPresent) {
if (uShadows.lightPosition.w == 0.0) {
// Directional light
@ -260,13 +276,13 @@ float getShadow() {
for (int x = -1; x <= 1; ++x) {
for (int y = -1; y <= 1; ++y) {
float pcfDepth = texture(uShadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
shadow += currentDepth > pcfDepth ? 1.0 : 0.0;
result += currentDepth > pcfDepth ? 1.0 : 0.0;
}
}
shadow /= 9.0;
result /= 9.0;
if (projCoords.z > 1.0) {
shadow = 0.0;
result = 0.0;
}
} else {
// Point light
@ -285,17 +301,17 @@ float getShadow() {
closestDepth *= SHADOW_FAR_PLANE;
if (currentDepth - bias > closestDepth) {
shadow += 1.0;
result += 1.0;
}
}
}
}
shadow /= samples * samples * samples;
}
result /= samples * samples * samples;
}
return uShadows.strength * shadow;
result *= uShadows.strength;
return result;
}
float getLightAttenuation(int light) {
@ -308,9 +324,10 @@ float getLightAttenuation(int light) {
return D / (D + r);
}
vec3 applyFog(vec3 rgb, float distance) {
vec3 applyFog(vec3 objectColor) {
float distance = length(uGeneral.cameraPosition.xyz - fragPosition);
float fogAmount = clamp(distance - uGeneral.fogNear, 0.0, uGeneral.fogFar - uGeneral.fogNear) / (uGeneral.fogFar - uGeneral.fogNear);
return mix(rgb, uGeneral.fogColor.rgb, fogAmount);
return mix(objectColor, uGeneral.fogColor.rgb, fogAmount);
}
)END";

View file

@ -229,7 +229,7 @@ uniform sampler2D uBRDFLookup;
uniform samplerCube uIrradianceMap;
uniform samplerCube uPrefilterMap;
void determineMetallicRoughness(vec4 diffuseSample, out float metallic, out float roughness) {
void getMetallicRoughness(vec4 diffuseSample, out float metallic, out float roughness) {
if (isFeatureEnabled(FEATURE_CUSTOMMAT) || !isFeatureEnabled(FEATURE_ENVMAP)) {
metallic = uMaterial.metallic;
roughness = uMaterial.roughness;
@ -240,31 +240,19 @@ void determineMetallicRoughness(vec4 diffuseSample, out float metallic, out floa
}
void main() {
vec2 texCoords = fragTexCoords + uGeneral.uvOffset;
vec4 diffuseSample;
if (isFeatureEnabled(FEATURE_DIFFUSE)) {
diffuseSample = texture(uDiffuse, texCoords);
} else {
diffuseSample = vec4(vec3(0.5), 1.0);
}
vec3 N;
if (isFeatureEnabled(FEATURE_BUMPMAPS)) {
N = getNormalFromBumpmap(texCoords);
} else {
N = normalize(fragNormal);
}
vec2 uv = getUV();
vec4 diffuseSample = texture(uDiffuse, uv);
vec3 cameraToFragment = uGeneral.cameraPosition.xyz - fragPosition;
vec3 V = normalize(cameraToFragment);
vec3 N = getNormal(uv);
vec3 R = reflect(-V, N);
vec3 albedo = isFeatureEnabled(FEATURE_HDR) ? pow(diffuseSample.rgb, vec3(GAMMA)) : diffuseSample.rgb;
float ao = 1.0;
float metallic, roughness;
determineMetallicRoughness(diffuseSample, metallic, roughness);
getMetallicRoughness(diffuseSample, metallic, roughness);
vec3 objectColor;
@ -360,7 +348,7 @@ void main() {
objectColor = pow(objectColor, vec3(1.0 / GAMMA));
}
if (isFeatureEnabled(FEATURE_FOG)) {
objectColor = applyFog(objectColor, length(cameraToFragment));
objectColor = applyFog(objectColor);
}
vec3 brightColor = vec3(0.0);

View file

@ -25,93 +25,14 @@ namespace reone {
namespace graphics {
char g_shaderFragmentBlinnPhong[] = R"END(
void main() {
vec2 texCoords = fragTexCoords + uGeneral.uvOffset;
vec4 diffuseSample = texture(uDiffuse, texCoords);
vec3 cameraToFragment = uGeneral.cameraPosition.xyz - fragPosition;
vec3 V = normalize(cameraToFragment);
vec3 N;
if (isFeatureEnabled(FEATURE_BUMPMAPS)) {
N = getNormalFromBumpmap(texCoords);
} else {
N = normalize(fragNormal);
}
vec3 objectColor;
if (isFeatureEnabled(FEATURE_LIGHTING)) {
objectColor = uGeneral.ambientColor.rgb * uMaterial.ambient.rgb * diffuseSample.rgb;
for (int i = 0; i < uLightCount; ++i) {
vec3 L = normalize(uLights[i].position.xyz - fragPosition);
vec3 H = normalize(V + L);
float diff = max(dot(L, N), 0.0);
vec3 diffuse = uLights[i].multiplier * uLights[i].color.rgb * diff * uMaterial.diffuse.rgb * diffuseSample.rgb;
float spec = pow(max(dot(N, H), 0.0), uMaterial.shininess);
vec3 specular = uLights[i].multiplier * uLights[i].color.rgb * spec * vec3(uMaterial.specular);
float attenuation = getLightAttenuation(i);
diffuse *= attenuation;
specular *= attenuation;
objectColor += diffuse + specular;
}
objectColor = min(objectColor, diffuseSample.rgb);
} else {
objectColor = diffuseSample.rgb;
}
if (isFeatureEnabled(FEATURE_LIGHTMAP)) {
vec4 lightmapSample = texture(uLightmap, fragLightmapCoords);
objectColor = mix(objectColor, objectColor * lightmapSample.rgb, isFeatureEnabled(FEATURE_WATER) ? 0.2 : 1.0);
}
if (isFeatureEnabled(FEATURE_ENVMAP)) {
vec3 R = reflect(-V, N);
vec4 envmapSample = texture(uEnvmap, R);
objectColor += (1.0 - diffuseSample.a) * envmapSample.rgb;
}
if (isFeatureEnabled(FEATURE_SHADOWS)) {
vec3 S = vec3(1.0) - max(vec3(0.0), vec3(getShadow()) - uGeneral.ambientColor.rgb);
objectColor *= S;
}
if (isFeatureEnabled(FEATURE_FOG)) {
objectColor = applyFog(objectColor, length(cameraToFragment));
}
float objectAlpha = uGeneral.alpha;
if (!isFeatureEnabled(FEATURE_ENVMAP) && !isFeatureEnabled(FEATURE_BUMPMAPS)) {
objectAlpha *= diffuseSample.a;
}
if (isFeatureEnabled(FEATURE_WATER)) {
objectColor *= uGeneral.waterAlpha;
objectAlpha *= uGeneral.waterAlpha;
}
vec3 brightColor = vec3(0.0);
if (isFeatureEnabled(FEATURE_SELFILLUM) && !isFeatureEnabled(FEATURE_WATER)) {
objectColor *= uGeneral.selfIllumColor.rgb;
brightColor = smoothstep(SELFILLUM_THRESHOLD, 1.0, uGeneral.selfIllumColor.rgb * diffuseSample.rgb * objectAlpha);
}
fragColor = vec4(objectColor, objectAlpha);
fragColorBright = vec4(brightColor, 1.0);
char g_shaderBaseBlinnPhong[] = R"END(
vec3 getLightingIndirect(vec3 N) {
return uGeneral.ambientColor.rgb * uMaterial.ambient.rgb;
}
)END";
char g_shaderFragmentBlinnPhongTextureless[] = R"END(
void main() {
vec3 indirect = uGeneral.ambientColor.rgb * uMaterial.ambient.rgb;
vec3 direct = vec3(0.0);
if (isFeatureEnabled(FEATURE_LIGHTING)) {
vec3 getLightingDirect(vec3 N) {
vec3 result = vec3(0.0);
vec3 V = normalize(uGeneral.cameraPosition.xyz - fragPosition);
vec3 N = normalize(fragNormal);
for (int i = 0; i < uLightCount; ++i) {
vec3 L = normalize(uLights[i].position.xyz - fragPosition);
@ -127,16 +48,87 @@ void main() {
diffuse *= attenuation;
specular *= attenuation;
direct += diffuse + specular;
}
} else if (isFeatureEnabled(FEATURE_LIGHTMAP)) {
indirect *= texture(uLightmap, fragLightmapCoords).rgb;
result += diffuse + specular;
}
vec3 objectColor = indirect + direct;
return result;
}
)END";
fragColor = vec4(objectColor, uGeneral.alpha);
fragColorBright = vec4(0.0);
char g_shaderFragmentBlinnPhong[] = R"END(
void main() {
vec2 uv = getUV();
vec3 N = getNormal(uv);
float shadow = getShadow();
vec4 diffuseSample = texture(uDiffuse, uv);
bool opaque = isFeatureEnabled(FEATURE_ENVMAP) || isFeatureEnabled(FEATURE_BUMPMAPS);
vec3 lighting;
if (isFeatureEnabled(FEATURE_LIGHTMAP)) {
vec4 lightmapSample = texture(uLightmap, fragLightmapCoords);
lighting = (1.0 - 0.5 * shadow) * lightmapSample.rgb;
if (isFeatureEnabled(FEATURE_WATER)) {
lighting *= 0.2;
}
} else if (isFeatureEnabled(FEATURE_LIGHTING)) {
vec3 indirect = getLightingIndirect(N);
vec3 direct = getLightingDirect(N);
lighting = min(vec3(1.0), indirect + (1.0 - shadow) * direct);
} else {
lighting = vec3(1.0);
}
vec3 objectColor = lighting * uGeneral.color.rgb * diffuseSample.rgb;
float objectAlpha = (opaque ? 1.0 : diffuseSample.a) * uGeneral.alpha;
if (isFeatureEnabled(FEATURE_ENVMAP)) {
vec3 V = normalize(uGeneral.cameraPosition.xyz - fragPosition);
vec3 R = reflect(-V, N);
vec4 envmapSample = texture(uEnvmap, R);
objectColor += (1.0 - diffuseSample.a) * envmapSample.rgb;
}
if (isFeatureEnabled(FEATURE_WATER)) {
objectColor *= uGeneral.waterAlpha;
objectAlpha *= uGeneral.waterAlpha;
}
if (isFeatureEnabled(FEATURE_FOG)) {
objectColor = applyFog(objectColor);
}
vec3 objectColorBright;
if (isFeatureEnabled(FEATURE_SELFILLUM)) {
objectColorBright = smoothstep(SELFILLUM_THRESHOLD, 1.0, uGeneral.selfIllumColor.rgb * diffuseSample.rgb * diffuseSample.a);
} else {
objectColorBright = vec3(0.0);
}
fragColor = vec4(objectColor, objectAlpha);
fragColorBright = vec4(objectColorBright, objectAlpha);
}
)END";
char g_shaderFragmentBlinnPhongDiffuseless[] = R"END(
void main() {
vec3 N = normalize(fragNormal);
float shadow = getShadow();
vec3 lighting;
if (isFeatureEnabled(FEATURE_LIGHTMAP)) {
vec4 lightmapSample = texture(uLightmap, fragLightmapCoords);
lighting = (1.0 - 0.5 * shadow) * lightmapSample.rgb;
} else if (isFeatureEnabled(FEATURE_LIGHTING)) {
vec3 indirect = getLightingIndirect(N);
vec3 direct = getLightingDirect(N);
lighting = min(vec3(1.0), indirect + (1.0 - shadow) * direct);
} else {
lighting = vec3(1.0);
}
vec3 objectColor = lighting * uGeneral.color.rgb;
float objectAlpha = uGeneral.alpha;
fragColor = vec4(objectColor, objectAlpha);
fragColorBright = vec4(vec3(0.0), objectAlpha);
}
)END";

View file

@ -242,7 +242,7 @@ void ModelNodeSceneNode::drawSingle(bool shadowPass) {
} else {
program = !_textures.diffuse ?
ShaderProgram::ModelBlinnPhongTextureless :
ShaderProgram::ModelBlinnPhongDiffuseless :
(isFeatureEnabled(Feature::PBR) ? ShaderProgram::ModelPBR : ShaderProgram::ModelBlinnPhong);
if (_textures.diffuse) {