From df5eec462451fdbe0192b71fa040aa5d594e47e7 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sun, 8 Dec 2019 06:29:41 +0100 Subject: [PATCH 1/8] computeLight: default PBR packing is ORM like glTF 2.0 --- .../renderer/glsl_source/computeLight_fp.glsl | 13 +++++++++++-- src/engine/renderer/tr_shader.cpp | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/engine/renderer/glsl_source/computeLight_fp.glsl b/src/engine/renderer/glsl_source/computeLight_fp.glsl index 35837209a7..08ed6fa261 100644 --- a/src/engine/renderer/glsl_source/computeLight_fp.glsl +++ b/src/engine/renderer/glsl_source/computeLight_fp.glsl @@ -56,8 +56,17 @@ void computeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightColor, float NdotH = clamp( dot( normal, H ), 0.0, 1.0 ); #if defined(USE_PHYSICAL_SHADING) - float metalness = specularColor.x; - float roughness = specularColor.y; + // Daemon PBR packing defaults to ORM like glTF 2.0 defines + // https://www.khronos.org/blog/art-pipeline-for-gltf + // > ORM texture for Occlusion, Roughness, and Metallic + // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/schema/material.pbrMetallicRoughness.schema.json#L45 + // > The metalness values are sampled from the B channel. The roughness values are sampled from the G channel. + // > These values are linear. If other channels are present (R or A), they are ignored for metallic-roughness calculations. + // https://docs.blender.org/manual/en/2.80/addons/io_scene_gltf2.html + // > glTF stores occlusion in the red (R) channel, allowing it to optionally share the same image + // > with the roughness and metallic channels. + float roughness = specularColor.g; + float metalness = specularColor.b; float NdotV = clamp( dot( normal, viewDir ), 0.0, 1.0); float VdotH = clamp( dot( viewDir, H ), 0.0, 1.0); diff --git a/src/engine/renderer/tr_shader.cpp b/src/engine/renderer/tr_shader.cpp index eb16d1f380..04c7993c56 100644 --- a/src/engine/renderer/tr_shader.cpp +++ b/src/engine/renderer/tr_shader.cpp @@ -1858,6 +1858,7 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) // use PBR instead } + // Daemon PBR packing defaults to ORM like glTF 2.0 stage->collapseType = collapseType_t::COLLAPSE_lighting_PBR; ParseMaterialMap( stage, text ); } From 579885e84ce3e66aec379fadaa3b2a8beef4437b Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Mon, 9 Dec 2019 01:08:08 +0100 Subject: [PATCH 2/8] renderer: default material is physical --- src/engine/renderer/tr_local.h | 10 +++++----- src/engine/renderer/tr_shade.cpp | 12 ++++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index f738d00823..0ab8292b43 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -1006,8 +1006,8 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) TB_DIFFUSEMAP = TB_COLORMAP, TB_REFLECTIONMAP = TB_COLORMAP, TB_NORMALMAP, - TB_SPECULARMAP, - TB_MATERIALMAP = TB_SPECULARMAP, + TB_MATERIALMAP, + TB_SPECULARMAP = TB_MATERIALMAP, TB_GLOWMAP, MAX_TEXTURE_BUNDLES }; @@ -1032,8 +1032,8 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) ST_GLOWMAP, ST_DIFFUSEMAP, ST_NORMALMAP, - ST_SPECULARMAP, ST_MATERIALMAP, + ST_SPECULARMAP, ST_REFLECTIONMAP, // cubeMap based reflection ST_REFRACTIONMAP, ST_DISPERSIONMAP, @@ -1043,8 +1043,8 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) ST_HEATHAZEMAP, // heatHaze post process effect ST_LIQUIDMAP, ST_LIGHTMAP, - ST_COLLAPSE_lighting_PHONG, // diffusemap + opt:normalmap + opt:glowmap + opt:specularmap - ST_COLLAPSE_lighting_PBR, // diffusemap + opt:normalmap + opt:glowmap + materialmap + ST_COLLAPSE_lighting_PBR, // map|diffusemap + opt:normalmap + opt:glowmap + opt:materialmap + ST_COLLAPSE_lighting_PHONG, // map|diffusemap + opt:normalmap + opt:glowmap + specularmap ST_COLLAPSE_reflection_CB, // color cubemap + normalmap // light shader stage types diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index f8e3f39d30..ffd89327b5 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -711,12 +711,15 @@ static void Render_vertexLighting_DBS_entity( int stage ) GL_State( stateBits ); + bool hasMaterialMap = pStage->bundle[ TB_MATERIALMAP ].image[ 0 ] != nullptr; + bool isMaterialPhysical = pStage->collapseType == collapseType_t::COLLAPSE_lighting_PBR; + bool normalMapping = r_normalMapping->integer && ( pStage->bundle[ TB_NORMALMAP ].image[ 0 ] != nullptr ); bool heightMapInNormalMap = pStage->heightMapInNormalMap && ( pStage->bundle[ TB_NORMALMAP ].image[ 0 ] != nullptr ); bool parallaxMapping = r_parallaxMapping->integer && tess.surfaceShader->parallax && !tess.surfaceShader->noParallax && heightMapInNormalMap; - bool specularMapping = r_specularMapping->integer && ( pStage->bundle[ TB_SPECULARMAP ].image[ 0 ] ); + bool physicalMapping = hasMaterialMap && isMaterialPhysical; + bool specularMapping = r_specularMapping->integer && hasMaterialMap && !isMaterialPhysical; bool glowMapping = r_glowMapping->integer && ( pStage->bundle[ TB_GLOWMAP ].image[ 0 ] != nullptr ); - bool materialMapping = pStage->collapseType == collapseType_t::COLLAPSE_lighting_PBR; // choose right shader program ---------------------------------- gl_vertexLightingShader_DBS_entity->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ); @@ -730,7 +733,7 @@ static void Render_vertexLighting_DBS_entity( int stage ) gl_vertexLightingShader_DBS_entity->SetReflectiveSpecular( normalMapping && tr.cubeHashTable != nullptr ); - gl_vertexLightingShader_DBS_entity->SetPhysicalShading( materialMapping ); + gl_vertexLightingShader_DBS_entity->SetPhysicalShading( physicalMapping ); gl_vertexLightingShader_DBS_entity->BindProgram( pStage->deformIndex ); @@ -940,7 +943,7 @@ static void Render_vertexLighting_DBS_world( int stage ) bool normalMapping = r_normalMapping->integer && ( pStage->bundle[ TB_NORMALMAP ].image[ 0 ] != nullptr ); bool heightMapInNormalMap = pStage->heightMapInNormalMap && ( pStage->bundle[ TB_NORMALMAP ].image[ 0 ] != nullptr ); bool parallaxMapping = r_parallaxMapping->integer && tess.surfaceShader->parallax && !tess.surfaceShader->noParallax && heightMapInNormalMap; - bool specularMapping = r_specularMapping->integer && ( pStage->bundle[ TB_SPECULARMAP ].image[ 0 ] ); + bool specularMapping = r_specularMapping->integer && ( pStage->bundle[ TB_SPECULARMAP ].image[ 0 ] != nullptr ); bool glowMapping = r_glowMapping->integer && ( pStage->bundle[ TB_GLOWMAP ].image[ 0 ] != nullptr ); // choose right shader program ---------------------------------- @@ -3161,6 +3164,7 @@ void Tess_StageIteratorLighting() switch ( diffuseStage->type ) { case stageType_t::ST_DIFFUSEMAP: + case stageType_t::ST_COLLAPSE_lighting_PBR: case stageType_t::ST_COLLAPSE_lighting_PHONG: if ( light->l.rlType == refLightType_t::RL_OMNI ) { From 7ce6cba43766ecb9f50f5561621377539fd08853 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 7 Dec 2019 13:57:12 +0100 Subject: [PATCH 3/8] renderer: add r_physicalMapping cvar, currently disabled --- src/engine/renderer/tr_init.cpp | 2 ++ src/engine/renderer/tr_local.h | 1 + src/engine/renderer/tr_shade.cpp | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index ecbb294e56..954e066fd6 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -158,6 +158,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *r_offsetFactor; cvar_t *r_offsetUnits; + cvar_t *r_physicalMapping; cvar_t *r_specularExponentMin; cvar_t *r_specularExponentMax; cvar_t *r_specularScale; @@ -1189,6 +1190,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_offsetFactor = ri.Cvar_Get( "r_offsetFactor", "-1", CVAR_CHEAT ); r_offsetUnits = ri.Cvar_Get( "r_offsetUnits", "-2", CVAR_CHEAT ); + r_physicalMapping = ri.Cvar_Get( "r_physicalMapping", "0", CVAR_ARCHIVE ); r_specularExponentMin = ri.Cvar_Get( "r_specularExponentMin", "0", CVAR_CHEAT ); r_specularExponentMax = ri.Cvar_Get( "r_specularExponentMax", "16", CVAR_CHEAT ); r_specularScale = ri.Cvar_Get( "r_specularScale", "1.0", CVAR_CHEAT | CVAR_LATCH ); diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 0ab8292b43..3b129874ed 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -2844,6 +2844,7 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) extern cvar_t *r_offsetFactor; extern cvar_t *r_offsetUnits; + extern cvar_t *r_physicalMapping; extern cvar_t *r_specularExponentMin; extern cvar_t *r_specularExponentMax; extern cvar_t *r_specularScale; diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index ffd89327b5..c46fcaeda4 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -717,7 +717,7 @@ static void Render_vertexLighting_DBS_entity( int stage ) bool normalMapping = r_normalMapping->integer && ( pStage->bundle[ TB_NORMALMAP ].image[ 0 ] != nullptr ); bool heightMapInNormalMap = pStage->heightMapInNormalMap && ( pStage->bundle[ TB_NORMALMAP ].image[ 0 ] != nullptr ); bool parallaxMapping = r_parallaxMapping->integer && tess.surfaceShader->parallax && !tess.surfaceShader->noParallax && heightMapInNormalMap; - bool physicalMapping = hasMaterialMap && isMaterialPhysical; + bool physicalMapping = r_physicalMapping->integer && hasMaterialMap && isMaterialPhysical; bool specularMapping = r_specularMapping->integer && hasMaterialMap && !isMaterialPhysical; bool glowMapping = r_glowMapping->integer && ( pStage->bundle[ TB_GLOWMAP ].image[ 0 ] != nullptr ); From 5dd263b9bfa4a65e6bd55e3caacd11cf5f8bc58c Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sun, 8 Dec 2019 06:50:54 +0100 Subject: [PATCH 4/8] bikeshedding: use material word instead of specular as it can store both specular or physical textures --- .../renderer/glsl_source/computeLight_fp.glsl | 18 +++++++++--------- .../glsl_source/forwardLighting_fp.glsl | 5 +++-- .../renderer/glsl_source/lightMapping_fp.glsl | 10 +++++----- .../vertexLighting_DBS_entity_fp.glsl | 6 +++--- .../vertexLighting_DBS_world_fp.glsl | 8 ++++---- 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/engine/renderer/glsl_source/computeLight_fp.glsl b/src/engine/renderer/glsl_source/computeLight_fp.glsl index 08ed6fa261..b047a20342 100644 --- a/src/engine/renderer/glsl_source/computeLight_fp.glsl +++ b/src/engine/renderer/glsl_source/computeLight_fp.glsl @@ -50,7 +50,7 @@ uniform vec2 u_SpecularExponent; // lighting helper functions void computeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightColor, - vec4 diffuseColor, vec4 specularColor, + vec4 diffuseColor, vec4 materialColor, inout vec4 accumulator ) { vec3 H = normalize( lightDir + viewDir ); float NdotH = clamp( dot( normal, H ), 0.0, 1.0 ); @@ -59,14 +59,14 @@ void computeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightColor, // Daemon PBR packing defaults to ORM like glTF 2.0 defines // https://www.khronos.org/blog/art-pipeline-for-gltf // > ORM texture for Occlusion, Roughness, and Metallic - // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/schema/material.pbrMetallicRoughness.schema.json#L45 + // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/schema/material.pbrMetallicRoughness.schema.json // > The metalness values are sampled from the B channel. The roughness values are sampled from the G channel. // > These values are linear. If other channels are present (R or A), they are ignored for metallic-roughness calculations. // https://docs.blender.org/manual/en/2.80/addons/io_scene_gltf2.html // > glTF stores occlusion in the red (R) channel, allowing it to optionally share the same image // > with the roughness and metallic channels. - float roughness = specularColor.g; - float metalness = specularColor.b; + float roughness = materialColor.g; + float metalness = materialColor.b; float NdotV = clamp( dot( normal, viewDir ), 0.0, 1.0); float VdotH = clamp( dot( viewDir, H ), 0.0, 1.0); @@ -103,7 +103,7 @@ void computeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightColor, accumulator.xyz += diffuseColor.xyz * lightColor.xyz * NdotL; #if defined(r_specularMapping) - accumulator.xyz += specularColor.xyz * lightColor.xyz * pow( NdotH, u_SpecularExponent.x * specularColor.w + u_SpecularExponent.y) * r_SpecularScale; + accumulator.xyz += materialColor.xyz * lightColor.xyz * pow( NdotH, u_SpecularExponent.x * materialColor.w + u_SpecularExponent.y) * r_SpecularScale; #endif // r_specularMapping #endif // USE_PHYSICAL_SHADING } @@ -138,7 +138,7 @@ int nextIdx( inout idxs_t idxs ) { const int numLayers = MAX_REF_LIGHTS / 256; void computeDLight( int idx, vec3 P, vec3 normal, vec3 viewDir, vec4 diffuse, - vec4 specular, inout vec4 color ) { + vec4 material, inout vec4 color ) { vec4 center_radius = GetLight( idx, center_radius ); vec4 color_type = GetLight( idx, color_type ); vec3 L; @@ -166,10 +166,10 @@ void computeDLight( int idx, vec3 P, vec3 normal, vec3 viewDir, vec4 diffuse, } computeLight( L, normal, viewDir, attenuation * attenuation * color_type.xyz, - diffuse, specular, color ); + diffuse, material, color ); } -void computeDLights( vec3 P, vec3 normal, vec3 viewDir, vec4 diffuse, vec4 specular, +void computeDLights( vec3 P, vec3 normal, vec3 viewDir, vec4 diffuse, vec4 material, inout vec4 color ) { vec2 tile = floor( gl_FragCoord.xy * (1.0 / float( TILE_SIZE ) ) ) + 0.5; vec3 tileScale = vec3( r_tileStep, 1.0/numLayers ); @@ -194,7 +194,7 @@ void computeDLights( vec3 P, vec3 normal, vec3 viewDir, vec4 diffuse, vec4 specu return; } - computeDLight( idx, P, normal, viewDir, diffuse, specular, color ); + computeDLight( idx, P, normal, viewDir, diffuse, material, color ); #if defined(r_showLightTiles) numLights++; diff --git a/src/engine/renderer/glsl_source/forwardLighting_fp.glsl b/src/engine/renderer/glsl_source/forwardLighting_fp.glsl index 098597de3b..503c575b1b 100644 --- a/src/engine/renderer/glsl_source/forwardLighting_fp.glsl +++ b/src/engine/renderer/glsl_source/forwardLighting_fp.glsl @@ -32,7 +32,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #endif uniform sampler2D u_DiffuseMap; -uniform sampler2D u_SpecularMap; +uniform sampler2D u_MaterialMap; uniform sampler2D u_AttenuationMapXY; uniform sampler2D u_AttenuationMapZ; @@ -976,8 +976,9 @@ void main() diffuse.rgb *= u_LightColor * NL; #if defined(r_specularMapping) + // FIXME: ignore if PBR // compute the specular term - vec4 spec = texture2D(u_SpecularMap, texCoords).rgba; + vec4 spec = texture2D(u_MaterialMap, texCoords).rgba; vec3 specular = spec.rgb * u_LightColor * pow(clamp(dot(normal, H), 0.0, 1.0), u_SpecularExponent.x * spec.a + u_SpecularExponent.y) * r_SpecularScale; #endif // r_specularMapping diff --git a/src/engine/renderer/glsl_source/lightMapping_fp.glsl b/src/engine/renderer/glsl_source/lightMapping_fp.glsl index 3bfa3831ca..94a89d5abe 100644 --- a/src/engine/renderer/glsl_source/lightMapping_fp.glsl +++ b/src/engine/renderer/glsl_source/lightMapping_fp.glsl @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* lightMapping_fp.glsl */ uniform sampler2D u_DiffuseMap; -uniform sampler2D u_SpecularMap; +uniform sampler2D u_MaterialMap; uniform sampler2D u_GlowMap; uniform sampler2D u_LightMap; uniform sampler2D u_DeluxeMap; @@ -66,8 +66,8 @@ void main() return; } - // compute the specular term - vec4 specular = texture2D(u_SpecularMap, texCoords); + // compute the material term + vec4 material = texture2D(u_MaterialMap, texCoords); // compute normal in world space from normalmap vec3 normal = NormalInWorldSpace(texCoords, tangentToWorldMatrix); @@ -88,13 +88,13 @@ void main() lightColor /= clamp(dot(normalize(var_Normal), L), 0.004, 1.0); // compute final color - computeLight( L, normal, viewDir, lightColor, diffuse, specular, color ); + computeLight( L, normal, viewDir, lightColor, diffuse, material, color ); #else // !USE_DELUXE_MAPPING // normal/deluxe mapping is disabled color.xyz += lightColor.xyz * diffuse.xyz; #endif // USE_DELUXE_MAPPING - computeDLights( var_Position, normal, viewDir, diffuse, specular, color ); + computeDLights( var_Position, normal, viewDir, diffuse, material, color ); #if defined(r_glowMapping) color.rgb += texture2D(u_GlowMap, texCoords).rgb; diff --git a/src/engine/renderer/glsl_source/vertexLighting_DBS_entity_fp.glsl b/src/engine/renderer/glsl_source/vertexLighting_DBS_entity_fp.glsl index 8ac0b0f613..d7389fc515 100644 --- a/src/engine/renderer/glsl_source/vertexLighting_DBS_entity_fp.glsl +++ b/src/engine/renderer/glsl_source/vertexLighting_DBS_entity_fp.glsl @@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* vertexLighting_DBS_entity_fp.glsl */ uniform sampler2D u_DiffuseMap; -uniform sampler2D u_SpecularMap; +uniform sampler2D u_MaterialMap; uniform sampler2D u_GlowMap; uniform samplerCube u_EnvironmentMap0; @@ -97,7 +97,7 @@ void main() #if defined(USE_REFLECTIVE_SPECULAR) // not implemented for PBR yet - vec4 specBase = texture2D(u_SpecularMap, texCoords).rgba; + vec4 specBase = texture2D(u_MaterialMap, texCoords).rgba; vec4 envColor0 = textureCube(u_EnvironmentMap0, reflect(-viewDir, normal)).rgba; vec4 envColor1 = textureCube(u_EnvironmentMap1, reflect(-viewDir, normal)).rgba; @@ -106,7 +106,7 @@ void main() #else // USE_REFLECTIVE_SPECULAR // simple Blinn-Phong - vec4 specBase = texture2D(u_SpecularMap, texCoords).rgba; + vec4 specBase = texture2D(u_MaterialMap, texCoords).rgba; #endif // USE_REFLECTIVE_SPECULAR diff --git a/src/engine/renderer/glsl_source/vertexLighting_DBS_world_fp.glsl b/src/engine/renderer/glsl_source/vertexLighting_DBS_world_fp.glsl index 4881134b1a..4e7242e24a 100644 --- a/src/engine/renderer/glsl_source/vertexLighting_DBS_world_fp.glsl +++ b/src/engine/renderer/glsl_source/vertexLighting_DBS_world_fp.glsl @@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* vertexLighting_DBS_world_fp.glsl */ uniform sampler2D u_DiffuseMap; -uniform sampler2D u_SpecularMap; +uniform sampler2D u_MaterialMap; uniform sampler2D u_GlowMap; uniform float u_AlphaThreshold; @@ -96,16 +96,16 @@ void main() return; } - vec4 specular = texture2D(u_SpecularMap, texCoords); + vec4 material = texture2D(u_MaterialMap, texCoords); // compute normal in world space from normalmap vec3 normal = NormalInWorldSpace(texCoords, tangentToWorldMatrix); // compute final color vec4 color = vec4( ambCol * diffuse.xyz, diffuse.a ); - computeLight( L, normal, viewDir, dirCol, diffuse, specular, color ); + computeLight( L, normal, viewDir, dirCol, diffuse, material, color ); - computeDLights( var_Position, normal, viewDir, diffuse, specular, color ); + computeDLights( var_Position, normal, viewDir, diffuse, material, color ); #if defined(r_glowMapping) color.rgb += texture2D(u_GlowMap, texCoords).rgb; From 7fa8f150ab9c2be3db055dadfa26a3ebf160c0da Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sun, 8 Dec 2019 07:58:49 +0100 Subject: [PATCH 5/8] tr_shade: enable PBR for lightMapping --- src/engine/renderer/tr_shade.cpp | 39 ++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index c46fcaeda4..ede6d025fa 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -810,15 +810,18 @@ static void Render_vertexLighting_DBS_entity( int stage ) GL_BindToTMU( 1, tr.flatImage ); } - if ( specularMapping ) + if ( physicalMapping || specularMapping ) { - // bind u_SpecularMap - GL_BindToTMU( 2, pStage->bundle[ TB_SPECULARMAP ].image[ 0 ] ); + // bind u_MaterialMap + GL_BindToTMU( 2, pStage->bundle[ TB_MATERIALMAP ].image[ 0 ] ); - float minSpec = RB_EvalExpression( &pStage->specularExponentMin, r_specularExponentMin->value ); - float maxSpec = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); + if ( specularMapping ) + { + float minSpec = RB_EvalExpression( &pStage->specularExponentMin, r_specularExponentMin->value ); + float maxSpec = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); - gl_vertexLightingShader_DBS_entity->SetUniform_SpecularExponent( minSpec, maxSpec ); + gl_vertexLightingShader_DBS_entity->SetUniform_SpecularExponent( minSpec, maxSpec ); + } } else { @@ -1136,15 +1139,18 @@ static void Render_lightMapping( int stage ) && (tess.surfaceShader->surfaceFlags & SURF_NOLIGHTMAP) && !(tess.numSurfaceStages > 0 && tess.surfaceStages[0]->rgbGen == colorGen_t::CGEN_VERTEX); + bool isMaterialPhysical = pStage->collapseType == collapseType_t::COLLAPSE_lighting_PBR; + bool hasNormalMap = pStage->bundle[ TB_NORMALMAP ].image[ 0 ] != nullptr; - bool hasSpecularMap = pStage->bundle[ TB_SPECULARMAP ].image[ 0 ] != nullptr; + bool hasMaterialMap = pStage->bundle[ TB_MATERIALMAP ].image[ 0 ] != nullptr; bool hasGlowMap = pStage->bundle[ TB_GLOWMAP ].image[ 0 ] != nullptr; bool normalMapping = r_normalMapping->integer && hasNormalMap; bool deluxeMapping = r_deluxeMapping->integer && tr.worldDeluxeMapping && normalMapping; bool heightMapInNormalMap = pStage->heightMapInNormalMap && hasNormalMap; bool parallaxMapping = r_parallaxMapping->integer && tess.surfaceShader->parallax && !tess.surfaceShader->noParallax && heightMapInNormalMap; - bool specularMapping = r_specularMapping->integer && hasSpecularMap; + bool physicalMapping = r_physicalMapping->integer && hasMaterialMap && isMaterialPhysical; + bool specularMapping = r_specularMapping->integer && hasMaterialMap && !isMaterialPhysical; bool glowMapping = r_glowMapping->integer && hasGlowMap; // choose right shader program ---------------------------------- @@ -1156,6 +1162,8 @@ static void Render_lightMapping( int stage ) tess.vboVertexSprite = false; + gl_lightMappingShader->SetPhysicalShading( physicalMapping ); + gl_lightMappingShader->BindProgram( pStage->deformIndex ); // end choose right shader program ------------------------------ @@ -1224,15 +1232,18 @@ static void Render_lightMapping( int stage ) GL_BindToTMU( 1, tr.flatImage ); } - if ( specularMapping ) + if ( physicalMapping || specularMapping ) { - // bind u_SpecularMap - GL_BindToTMU( 2, pStage->bundle[ TB_SPECULARMAP ].image[ 0 ] ); + // bind u_MaterialMap + GL_BindToTMU( 2, pStage->bundle[ TB_MATERIALMAP ].image[ 0 ] ); - float specExpMin = RB_EvalExpression( &pStage->specularExponentMin, r_specularExponentMin->value ); - float specExpMax = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); + if ( specularMapping ) + { + float specExpMin = RB_EvalExpression( &pStage->specularExponentMin, r_specularExponentMin->value ); + float specExpMax = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); - gl_lightMappingShader->SetUniform_SpecularExponent( specExpMin, specExpMax ); + gl_lightMappingShader->SetUniform_SpecularExponent( specExpMin, specExpMax ); + } } else { From ed2459205b67eba71b5a95dd8ea38e50e002052f Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Thu, 12 Dec 2019 08:46:38 +0100 Subject: [PATCH 6/8] renderer: PBR map keyword is physicalMap --- src/engine/renderer/tr_local.h | 5 +-- src/engine/renderer/tr_shader.cpp | 58 +++++++++++++++---------------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 3b129874ed..69971a53c2 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -1007,6 +1007,7 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) TB_REFLECTIONMAP = TB_COLORMAP, TB_NORMALMAP, TB_MATERIALMAP, + TB_PHYSICALMAP = TB_MATERIALMAP, TB_SPECULARMAP = TB_MATERIALMAP, TB_GLOWMAP, MAX_TEXTURE_BUNDLES @@ -1032,7 +1033,7 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) ST_GLOWMAP, ST_DIFFUSEMAP, ST_NORMALMAP, - ST_MATERIALMAP, + ST_PHYSICALMAP, ST_SPECULARMAP, ST_REFLECTIONMAP, // cubeMap based reflection ST_REFRACTIONMAP, @@ -1043,7 +1044,7 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) ST_HEATHAZEMAP, // heatHaze post process effect ST_LIQUIDMAP, ST_LIGHTMAP, - ST_COLLAPSE_lighting_PBR, // map|diffusemap + opt:normalmap + opt:glowmap + opt:materialmap + ST_COLLAPSE_lighting_PBR, // map|diffusemap + opt:normalmap + opt:glowmap + opt:physicalmap ST_COLLAPSE_lighting_PHONG, // map|diffusemap + opt:normalmap + opt:glowmap + specularmap ST_COLLAPSE_reflection_CB, // color cubemap + normalmap diff --git a/src/engine/renderer/tr_shader.cpp b/src/engine/renderer/tr_shader.cpp index 04c7993c56..2289605ac3 100644 --- a/src/engine/renderer/tr_shader.cpp +++ b/src/engine/renderer/tr_shader.cpp @@ -1649,12 +1649,12 @@ static void ParseSpecularMap( shaderStage_t *stage, const char **text, const int } } -static void ParseMaterialMap( shaderStage_t *stage, const char **text, const int bundleIndex = TB_MATERIALMAP ) +static void ParsePhysicalMap( shaderStage_t *stage, const char **text, const int bundleIndex = TB_PHYSICALMAP ) { char buffer[ 1024 ] = ""; stage->active = true; - stage->type = stageType_t::ST_MATERIALMAP; + stage->type = stageType_t::ST_PHYSICALMAP; stage->rgbGen = colorGen_t::CGEN_IDENTITY; stage->stateBits = GLS_DEFAULT; @@ -1830,13 +1830,13 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) { if ( stage->collapseType == collapseType_t::COLLAPSE_reflection_CB ) { - Log::Warn("Supposedly you shouldn't have a materialMap after a reflectionMap (in shader '%s')?", shader.name); + Log::Warn("Supposedly you shouldn't have a physicalMap after a reflectionMap (in shader '%s')?", shader.name); // use PHONG instead } if ( stage->collapseType == collapseType_t::COLLAPSE_lighting_PBR ) { - Log::Warn("Supposedly you shouldn't have a specularMap after a materialMap (in shader '%s')?", shader.name); + Log::Warn("Supposedly you shouldn't have a specularMap after a physicalMap (in shader '%s')?", shader.name); // keep PBR instead } else @@ -1845,22 +1845,22 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) ParseSpecularMap( stage, text ); } } - else if ( !Q_stricmp( token, "materialMap" ) ) + else if ( !Q_stricmp( token, "physicalMap" ) ) { if ( stage->collapseType == collapseType_t::COLLAPSE_reflection_CB ) { - Log::Warn("Supposedly you shouldn't have a materialMap after a reflectionMap (in shader '%s')?", shader.name); + Log::Warn("Supposedly you shouldn't have a physicalMap after a reflectionMap (in shader '%s')?", shader.name); // use PBR instead } else if ( stage->collapseType == collapseType_t::COLLAPSE_lighting_PHONG ) { - Log::Warn("Supposedly you shouldn't have a materialMap after a specularMap (in shader '%s')?", shader.name); + Log::Warn("Supposedly you shouldn't have a physicalMap after a specularMap (in shader '%s')?", shader.name); // use PBR instead } // Daemon PBR packing defaults to ORM like glTF 2.0 stage->collapseType = collapseType_t::COLLAPSE_lighting_PBR; - ParseMaterialMap( stage, text ); + ParsePhysicalMap( stage, text ); } else if ( !Q_stricmp( token, "glowMap" ) ) { @@ -1876,7 +1876,7 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) if ( stage->collapseType == collapseType_t::COLLAPSE_lighting_PBR || stage->collapseType == collapseType_t::COLLAPSE_lighting_PHONG ) { - Log::Warn("Supposedly you shouldn't have a reflectionMap after a materialMap or a specularMap (in shader '%s')?", shader.name); + Log::Warn("Supposedly you shouldn't have a reflectionMap after a physicalMap or a specularMap (in shader '%s')?", shader.name); // use reflectionMap instead } @@ -1888,7 +1888,7 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) if ( stage->collapseType == collapseType_t::COLLAPSE_lighting_PBR || stage->collapseType == collapseType_t::COLLAPSE_lighting_PHONG ) { - Log::Warn("Supposedly you shouldn't have a reflectionMapBlended after a materialMap or a specularMap (in shader '%s')?", shader.name); + Log::Warn("Supposedly you shouldn't have a reflectionMapBlended after a physicalMap or a specularMap (in shader '%s')?", shader.name); // use reflectionMapBlended instead } @@ -2259,10 +2259,10 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) Log::Warn("deprecated idTech4 blend parameter '%s' in shader '%s', better use it in place of 'map' keyword and pack related textures within the same stage", token, shader.name ); stage->type = stageType_t::ST_SPECULARMAP; } - else if ( !Q_stricmp( token, "materialMap" ) ) + else if ( !Q_stricmp( token, "physicalMap" ) ) { Log::Warn("deprecated idTech4 blend parameter '%s' in shader '%s', better use it in place of 'map' keyword and pack related textures within the same stage", token, shader.name ); - stage->type = stageType_t::ST_MATERIALMAP; + stage->type = stageType_t::ST_PHYSICALMAP; } else if ( !Q_stricmp( token, "glowMap" ) ) { @@ -2332,10 +2332,10 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) Log::Warn("deprecated XreaL stage parameter '%s' in shader '%s', better use it in place of 'map' keyword and pack related textures within the same stage", token, shader.name ); stage->type = stageType_t::ST_SPECULARMAP; } - else if ( !Q_stricmp( token, "materialMap" ) ) + else if ( !Q_stricmp( token, "physicalMap" ) ) { Log::Warn("deprecated XreaL stage parameter '%s' in shader '%s', better use it in place of 'map' keyword and pack related textures within the same stage", token, shader.name ); - stage->type = stageType_t::ST_MATERIALMAP; + stage->type = stageType_t::ST_PHYSICALMAP; } else if ( !Q_stricmp( token, "glowMap" ) ) { @@ -4168,11 +4168,11 @@ static bool ParseShader( const char *_text ) s++; continue; } - // materialMap - else if ( !Q_stricmp( token, "materialMap" ) ) + // physicalMap + else if ( !Q_stricmp( token, "physicalMap" ) ) { Log::Warn("deprecated idTech4 standalone stage '%s' in shader '%s', better move this line and pack related textures within one single curly bracket stage pair", token, shader.name ); - ParseMaterialMap( &stages[ s ], text, TB_COLORMAP ); + ParsePhysicalMap( &stages[ s ], text, TB_COLORMAP ); s++; continue; } @@ -4339,7 +4339,7 @@ static void CollapseStages() int diffuseStage = -1; int normalStage = -1; int specularStage = -1; - int materialStage = -1; + int physicalStage = -1; int reflectionStage = -1; int lightStage = -1; int glowStage = -1; @@ -4399,15 +4399,15 @@ static void CollapseStages() specularStage = i; } } - else if ( stages[ i ].type == stageType_t::ST_MATERIALMAP ) + else if ( stages[ i ].type == stageType_t::ST_PHYSICALMAP ) { - if ( materialStage != -1 ) + if ( physicalStage != -1 ) { - Log::Warn( "more than one material map stage in shader '%s'", shader.name ); + Log::Warn( "more than one physical map stage in shader '%s'", shader.name ); } else { - materialStage = i; + physicalStage = i; } } else if ( stages[ i ].type == stageType_t::ST_REFLECTIONMAP ) @@ -4478,7 +4478,7 @@ static void CollapseStages() if ( diffuseStage != -1 && ( specularStage != -1 || normalStage != -1 - || materialStage != -1 + || physicalStage != -1 || lightStage != -1 || glowStage != -1 ) ) { @@ -4486,13 +4486,13 @@ static void CollapseStages() // it would have to be backed-up somewhere - if ( specularStage != -1 && materialStage != -1 ) + if ( specularStage != -1 && physicalStage != -1 ) { - Log::Warn("Supposedly you shouldn't have both specularMap and materialMap (in shader '%s')?", shader.name); + Log::Warn("Supposedly you shouldn't have both specularMap and physicalMap (in shader '%s')?", shader.name); } else { - if ( materialStage != -1 ) + if ( physicalStage != -1 ) { Log::Debug("found PBR lighting collapsible stage in shader '%s'", shader.name); stages[ diffuseStage ].collapseType = collapseType_t::COLLAPSE_lighting_PBR; @@ -4522,12 +4522,12 @@ static void CollapseStages() // disable since it's merged stages[ specularStage ].active = false; } - if ( materialStage != -1 ) + if ( physicalStage != -1 ) { // merge with diffuse stage - stages[ diffuseStage ].bundle[ TB_MATERIALMAP ] = stages[ materialStage ].bundle[ TB_COLORMAP ]; + stages[ diffuseStage ].bundle[ TB_PHYSICALMAP ] = stages[ physicalStage ].bundle[ TB_COLORMAP ]; // disable since it's merged - stages[ materialStage ].active = false; + stages[ physicalStage ].active = false; } // always test for this stage before glow stage if ( lightStage != -1 ) From 1df33dd9698251965e56a7736a87f9499e348797 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Fri, 13 Dec 2019 07:21:29 +0100 Subject: [PATCH 7/8] glsl/forwardLighting: do not compute specularity with physical map --- src/engine/renderer/glsl_source/forwardLighting_fp.glsl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/renderer/glsl_source/forwardLighting_fp.glsl b/src/engine/renderer/glsl_source/forwardLighting_fp.glsl index 503c575b1b..09a64759a3 100644 --- a/src/engine/renderer/glsl_source/forwardLighting_fp.glsl +++ b/src/engine/renderer/glsl_source/forwardLighting_fp.glsl @@ -975,12 +975,13 @@ void main() } diffuse.rgb *= u_LightColor * NL; +#if !defined(USE_PHYSICAL_SHADING) #if defined(r_specularMapping) - // FIXME: ignore if PBR // compute the specular term vec4 spec = texture2D(u_MaterialMap, texCoords).rgba; vec3 specular = spec.rgb * u_LightColor * pow(clamp(dot(normal, H), 0.0, 1.0), u_SpecularExponent.x * spec.a + u_SpecularExponent.y) * r_SpecularScale; #endif // r_specularMapping +#endif // !USE_PHYSICAL_SHADING // compute light attenuation #if defined(LIGHT_PROJ) @@ -999,9 +1000,11 @@ void main() // compute final color vec4 color = diffuse; +#if !defined(USE_PHYSICAL_SHADING) #if defined(r_specularMapping) color.rgb += specular; #endif // r_specularMapping +#endif // !USE_PHYSICAL_SHADING #if !defined(LIGHT_DIRECTIONAL) color.rgb *= attenuationXY; From 48e257d0e807ec1b1d82c28f14c0f29cf8884fde Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sun, 15 Dec 2019 18:10:52 +0100 Subject: [PATCH 8/8] renderer: make r_physicalMapping a define and properly test for physical map --- src/engine/renderer/gl_shader.cpp | 5 +++++ src/engine/renderer/glsl_source/computeLight_fp.glsl | 10 +++++----- src/engine/renderer/tr_init.cpp | 2 +- src/engine/renderer/tr_shade.cpp | 4 ++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 167fce2b83..1fd83bfb98 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -589,6 +589,11 @@ static std::string GenEngineConstants() { AddDefine( str, "r_specularMapping", 1 ); } + if ( r_physicalMapping->integer ) + { + AddDefine( str, "r_physicalMapping", 1 ); + } + if ( r_glowMapping->integer ) { AddDefine( str, "r_glowMapping", 1 ); diff --git a/src/engine/renderer/glsl_source/computeLight_fp.glsl b/src/engine/renderer/glsl_source/computeLight_fp.glsl index b047a20342..632a1f4d2c 100644 --- a/src/engine/renderer/glsl_source/computeLight_fp.glsl +++ b/src/engine/renderer/glsl_source/computeLight_fp.glsl @@ -55,7 +55,7 @@ void computeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightColor, vec3 H = normalize( lightDir + viewDir ); float NdotH = clamp( dot( normal, H ), 0.0, 1.0 ); -#if defined(USE_PHYSICAL_SHADING) +#if defined(r_physicalMapping) && defined(USE_PHYSICAL_SHADING) // Daemon PBR packing defaults to ORM like glTF 2.0 defines // https://www.khronos.org/blog/art-pipeline-for-gltf // > ORM texture for Occlusion, Roughness, and Metallic @@ -89,7 +89,7 @@ void computeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightColor, accumulator.xyz += lightColor.xyz * (1.0 - metalness) * NdotL * diffuseColor.xyz; accumulator.xyz += lightColor.xyz * vec3((D * F * G) / (4.0 * NdotV)); accumulator.a = mix(diffuseColor.a, 1.0, FexpNV); -#else // !USE_PHYSICAL_SHADING +#else // !r_physicalMapping || !USE_PHYSICAL_SHADING float NdotL = dot( normal, lightDir ); #if defined(r_HalfLambertLighting) // http://developer.valvesoftware.com/wiki/Half_Lambert @@ -102,10 +102,10 @@ void computeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightColor, #endif accumulator.xyz += diffuseColor.xyz * lightColor.xyz * NdotL; -#if defined(r_specularMapping) +#if defined(r_specularMapping) && !defined(USE_PHYSICAL_SHADING) accumulator.xyz += materialColor.xyz * lightColor.xyz * pow( NdotH, u_SpecularExponent.x * materialColor.w + u_SpecularExponent.y) * r_SpecularScale; -#endif // r_specularMapping -#endif // USE_PHYSICAL_SHADING +#endif // r_specularMapping && !USE_PHYSICAL_SHADING& +#endif // !r_physicalMapping || !USE_PHYSICAL_SHADING } #if defined(TEXTURE_INTEGER) diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index 954e066fd6..bafbfb6f1f 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -1190,7 +1190,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_offsetFactor = ri.Cvar_Get( "r_offsetFactor", "-1", CVAR_CHEAT ); r_offsetUnits = ri.Cvar_Get( "r_offsetUnits", "-2", CVAR_CHEAT ); - r_physicalMapping = ri.Cvar_Get( "r_physicalMapping", "0", CVAR_ARCHIVE ); + r_physicalMapping = ri.Cvar_Get( "r_physicalMapping", "0", CVAR_LATCH ); r_specularExponentMin = ri.Cvar_Get( "r_specularExponentMin", "0", CVAR_CHEAT ); r_specularExponentMax = ri.Cvar_Get( "r_specularExponentMax", "16", CVAR_CHEAT ); r_specularScale = ri.Cvar_Get( "r_specularScale", "1.0", CVAR_CHEAT | CVAR_LATCH ); diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index ede6d025fa..92c9cfadc6 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -733,7 +733,7 @@ static void Render_vertexLighting_DBS_entity( int stage ) gl_vertexLightingShader_DBS_entity->SetReflectiveSpecular( normalMapping && tr.cubeHashTable != nullptr ); - gl_vertexLightingShader_DBS_entity->SetPhysicalShading( physicalMapping ); + gl_vertexLightingShader_DBS_entity->SetPhysicalShading( isMaterialPhysical ); gl_vertexLightingShader_DBS_entity->BindProgram( pStage->deformIndex ); @@ -1162,7 +1162,7 @@ static void Render_lightMapping( int stage ) tess.vboVertexSprite = false; - gl_lightMappingShader->SetPhysicalShading( physicalMapping ); + gl_lightMappingShader->SetPhysicalShading( isMaterialPhysical ); gl_lightMappingShader->BindProgram( pStage->deformIndex );