From a4d1d8a3bc08313777d9e0c6c81b46e5a13a5b44 Mon Sep 17 00:00:00 2001 From: zhuxudong Date: Wed, 3 Jan 2024 12:05:32 +0800 Subject: [PATCH 1/2] feat: support lightmap --- packages/core/src/material/PBRBaseMaterial.ts | 52 +++++++++++++++++++ packages/core/src/shaderlib/common_vert.glsl | 4 ++ .../src/shaderlib/pbr/ibl_frag_define.glsl | 13 +++++ packages/core/src/shaderlib/pbr/pbr_frag.glsl | 23 ++++++-- .../src/shaderlib/pbr/pbr_frag_define.glsl | 7 +++ packages/core/src/shaderlib/uv_share.glsl | 4 ++ packages/core/src/shaderlib/uv_vert.glsl | 4 ++ 7 files changed, 102 insertions(+), 5 deletions(-) diff --git a/packages/core/src/material/PBRBaseMaterial.ts b/packages/core/src/material/PBRBaseMaterial.ts index f421a92cb6..aaa217904c 100644 --- a/packages/core/src/material/PBRBaseMaterial.ts +++ b/packages/core/src/material/PBRBaseMaterial.ts @@ -20,6 +20,10 @@ export abstract class PBRBaseMaterial extends BaseMaterial { private static _clearCoatRoughnessTextureProp = ShaderProperty.getByName("material_ClearCoatRoughnessTexture"); private static _clearCoatNormalTextureProp = ShaderProperty.getByName("material_ClearCoatNormalTexture"); + private static _lightmapProp = ShaderProperty.getByName("material_Lightmap"); + private static _dirLightmapProp = ShaderProperty.getByName("material_DirLightmap"); + private static _lightmapTilingOffsetProp: ShaderProperty = ShaderProperty.getByName("material_LightmapTilingOffset"); + /** * Base color. */ @@ -243,6 +247,52 @@ export abstract class PBRBaseMaterial extends BaseMaterial { } } + /** + * Tiling and offset of lightmap textures. + */ + get lightmapTilingOffset(): Vector4 { + return this.shaderData.getVector4(PBRBaseMaterial._lightmapTilingOffsetProp); + } + + set lightmapTilingOffset(value: Vector4) { + const tilingOffset = this.shaderData.getVector4(PBRBaseMaterial._lightmapTilingOffsetProp); + if (value !== tilingOffset) { + tilingOffset.copyFrom(value); + } + } + + /** + * Lightmap. + */ + get lightmap(): Texture2D { + return this.shaderData.getTexture(PBRBaseMaterial._lightmapProp); + } + + set lightmap(value: Texture2D) { + this.shaderData.setTexture(PBRBaseMaterial._lightmapProp, value); + if (value) { + this.shaderData.enableMacro("MATERIAL_HAS_LIGHTMAP"); + } else { + this.shaderData.disableMacro("MATERIAL_HAS_LIGHTMAP"); + } + } + + /** + * Directional Lightmap. + */ + get dirLightmap(): Texture2D { + return this.shaderData.getTexture(PBRBaseMaterial._dirLightmapProp); + } + + set dirLightmap(value: Texture2D) { + this.shaderData.setTexture(PBRBaseMaterial._dirLightmapProp, value); + if (value) { + this.shaderData.enableMacro("MATERIAL_HAS_DIRLIGHTMAP"); + } else { + this.shaderData.disableMacro("MATERIAL_HAS_DIRLIGHTMAP"); + } + } + /** * Create a pbr base material instance. * @param engine - Engine to which the material belongs @@ -266,5 +316,7 @@ export abstract class PBRBaseMaterial extends BaseMaterial { shaderData.setFloat(PBRBaseMaterial._clearCoatProp, 0); shaderData.setFloat(PBRBaseMaterial._clearCoatRoughnessProp, 0); + + shaderData.setVector4(PBRBaseMaterial._lightmapTilingOffsetProp, new Vector4(1, 1, 0, 0)); } } diff --git a/packages/core/src/shaderlib/common_vert.glsl b/packages/core/src/shaderlib/common_vert.glsl index 7de75ee182..e68bccb400 100644 --- a/packages/core/src/shaderlib/common_vert.glsl +++ b/packages/core/src/shaderlib/common_vert.glsl @@ -46,6 +46,10 @@ attribute vec3 POSITION; uniform vec4 material_TilingOffset; +#ifdef MATERIAL_HAS_LIGHTMAP + uniform vec4 material_LightmapTilingOffset; +#endif + #ifndef MATERIAL_OMIT_NORMAL #ifdef RENDERER_HAS_NORMAL diff --git a/packages/core/src/shaderlib/pbr/ibl_frag_define.glsl b/packages/core/src/shaderlib/pbr/ibl_frag_define.glsl index 8d740d48cd..6894294f71 100644 --- a/packages/core/src/shaderlib/pbr/ibl_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/ibl_frag_define.glsl @@ -19,6 +19,19 @@ vec3 getLightProbeIrradiance(vec3 sh[9], vec3 normal){ } +vec3 DecodeDirectionalLightmap(vec3 color, vec4 dirTex, vec3 normalWorld) { + // In directional (non-specular) mode Enlighten bakes dominant light direction + // in a way, that using it for half Lambert and then dividing by a "rebalancing coefficient" + // gives a result close to plain diffuse response lightmaps, but normalmapped. + + // Note that dir is not unit length on purpose. Its length is "directionality", like + // for the directional specular lightmaps. + + float halfLambert = dot(normalWorld, dirTex.xyz - 0.5) + 0.5; + + return color * halfLambert / max(1e-4, dirTex.w); +} + // ------------------------Specular------------------------ // ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile diff --git a/packages/core/src/shaderlib/pbr/pbr_frag.glsl b/packages/core/src/shaderlib/pbr/pbr_frag.glsl index 626960c3e3..edb9bc6914 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag.glsl @@ -9,16 +9,29 @@ initMaterial(material, geometry); addTotalDirectRadiance(geometry, material, reflectedLight); // IBL diffuse -#ifdef SCENE_USE_SH - vec3 irradiance = getLightProbeIrradiance(scene_EnvSH, geometry.normal); +#ifdef MATERIAL_HAS_LIGHTMAP + vec4 lightmapColor= texture2D(material_Lightmap, v_lightmapUV); + // @TODO: use RGBM format from editor bake workflow. + vec3 irradiance = RGBMToLinear(lightmapColor, 1.0).rgb; + #ifdef MATERIAL_HAS_DIRLIGHTMAP + vec4 dirLightmapColor = texture2D (material_DirLightmap, v_lightmapUV); + irradiance = DecodeDirectionalLightmap (irradiance, dirLightmapColor, geometry.normal); + #endif #ifdef ENGINE_IS_COLORSPACE_GAMMA irradiance = linearToGamma(vec4(irradiance, 1.0)).rgb; #endif - irradiance *= scene_EnvMapLight.diffuseIntensity; #else - vec3 irradiance = scene_EnvMapLight.diffuse * scene_EnvMapLight.diffuseIntensity; - irradiance *= PI; + #ifdef SCENE_USE_SH + vec3 irradiance = getLightProbeIrradiance(scene_EnvSH, geometry.normal); + #ifdef ENGINE_IS_COLORSPACE_GAMMA + irradiance = linearToGamma(vec4(irradiance, 1.0)).rgb; + #endif + #else + vec3 irradiance = scene_EnvMapLight.diffuse * PI; // spherical convolution + #endif #endif +irradiance *= scene_EnvMapLight.diffuseIntensity; + reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor ); diff --git a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl index dd79b77cda..d366bbb0a2 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl @@ -63,6 +63,13 @@ uniform float material_OcclusionTextureCoord; uniform sampler2D material_OcclusionTexture; #endif +#ifdef MATERIAL_HAS_LIGHTMAP + uniform sampler2D material_Lightmap; + #ifdef MATERIAL_HAS_DIRLIGHTMAP + uniform sampler2D material_DirLightmap; + #endif +#endif + // Runtime struct ReflectedLight { vec3 directDiffuse; diff --git a/packages/core/src/shaderlib/uv_share.glsl b/packages/core/src/shaderlib/uv_share.glsl index 590922a16b..719d3f4596 100644 --- a/packages/core/src/shaderlib/uv_share.glsl +++ b/packages/core/src/shaderlib/uv_share.glsl @@ -2,4 +2,8 @@ varying vec2 v_uv; #ifdef RENDERER_HAS_UV1 varying vec2 v_uv1; +#endif + +#ifdef MATERIAL_HAS_LIGHTMAP + varying vec2 v_lightmapUV; #endif \ No newline at end of file diff --git a/packages/core/src/shaderlib/uv_vert.glsl b/packages/core/src/shaderlib/uv_vert.glsl index 3daaefea12..dfc309626b 100644 --- a/packages/core/src/shaderlib/uv_vert.glsl +++ b/packages/core/src/shaderlib/uv_vert.glsl @@ -11,4 +11,8 @@ #ifdef MATERIAL_NEED_TILING_OFFSET v_uv = v_uv * material_TilingOffset.xy + material_TilingOffset.zw; +#endif + +#ifdef MATERIAL_HAS_LIGHTMAP + v_lightmapUV = v_uv1 * material_LightmapTilingOffset.xy + material_LightmapTilingOffset.zw; #endif \ No newline at end of file From e97741079c0f5e0360405e63398222f8769e87b3 Mon Sep 17 00:00:00 2001 From: zhuxudong Date: Wed, 3 Jan 2024 15:33:29 +0800 Subject: [PATCH 2/2] refactor: use 5.0 as RGBM from editor --- packages/core/src/shaderlib/pbr/pbr_frag.glsl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/core/src/shaderlib/pbr/pbr_frag.glsl b/packages/core/src/shaderlib/pbr/pbr_frag.glsl index edb9bc6914..23fafff6a1 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag.glsl @@ -11,8 +11,7 @@ addTotalDirectRadiance(geometry, material, reflectedLight); // IBL diffuse #ifdef MATERIAL_HAS_LIGHTMAP vec4 lightmapColor= texture2D(material_Lightmap, v_lightmapUV); - // @TODO: use RGBM format from editor bake workflow. - vec3 irradiance = RGBMToLinear(lightmapColor, 1.0).rgb; + vec3 irradiance = RGBMToLinear(lightmapColor, 5.0).rgb; #ifdef MATERIAL_HAS_DIRLIGHTMAP vec4 dirLightmapColor = texture2D (material_DirLightmap, v_lightmapUV); irradiance = DecodeDirectionalLightmap (irradiance, dirLightmapColor, geometry.normal);