2026-01-28 17:19:36 +08:00
( function ( ) { "use strict" ; try { if ( typeof document < "u" ) { var e = document . createElement ( "style" ) ; e . appendChild ( document . createTextNode ( ' . bim - engine - wrapper { position : relative ; width : 100 % ; height : 100 % ; font - family : sans - serif ; box - sizing : border - box ; overflow : hidden ; background : linear - gradient ( to bottom , # d6e0eb , # f6faff ) } . bim - engine - opt - btn - container { z - index : 100 } . bim - construct - tree - btn { position : absolute ; top : 20 px ; left : 20 px ! important ; z - index : 100 } . bim - btn - group - root { display : flex ; gap : 8 px ; z - index : 1000 ; position : absolute ; pointer - events : auto } . bim - btn - group - root . static { position : relative ; inset : auto ; transform : none } . bim - btn - group - root . dir - row { flex - direction : row ; align - items : center } . bim - btn - group - root . dir - column { flex - direction : column ; align - items : stretch } . bim - btn - group - section { display : flex ; gap : 4 px ; background - color : var ( -- bim - btn - group - section - bg , rgba ( 17 , 17 , 17 , . 88 ) ) ; border - radius : 6 px ; padding : 4 px ; box - shadow : 0 2 px 8 px # 0000004 d , 0 1 px 3 px # 0003 } . bim - btn - group - root . dir - row . bim - btn - group - section { flex - direction : row ; align - items : center } . bim - btn - group - root . dir - column . bim - btn - group - section { flex - direction : column } . opt - btn - wrapper { position : relative } . opt - btn { display : flex ; cursor : pointer ; border - radius : 4 px ; transition : background - color . 2 s , color . 2 s , border - color . 2 s ; color : var ( -- bim - btn - text - color , # ccc ) ; background - color : var ( -- bim - btn - bg , transparent ) ; padding : 6 px ; align - items : center ; position : relative ; justify - content : center ; border : 1 px solid transparent ; outline : none } . opt - btn : hover { background - color : var ( -- bim - btn - hover - bg , # 444 ) } . opt - btn . active { background - color : var ( -- bim - btn - active - bg , rgba ( 255 , 255 , 255 , . 15 ) ) ; color : var ( -- bim - btn - text - active - color , # fff ) } . opt - btn . disabled { opacity : . 5 ; cursor : not - allowed } . opt - btn - icon { width : var ( -- bim - icon - size , 24 px ) ; height : var ( -- bim - icon - size , 24 px ) ; display : flex ; align - items : center ; justify - content : center ; color : var ( -- bim - icon - color , # ccc ) ; flex - shrink : 0 } . opt - btn - icon svg { width : 100 % ; height : 100 % ; fill : currentColor } . opt - btn - arrow { font - size : 10 px ; opacity : . 6 ; transition : transform . 2 s ; display : inline - block ; margin - left : 4 px } . opt - btn - arrow . rotated { transform : rotate ( 180 deg ) } . opt - btn - text - wrapper { display : flex ; align - items : center ; justify - content : center ; pointer - events : none } . opt - btn - label { display : inline } . opt - btn . no - label . opt - btn - label { display : none } . opt - btn . align - vertical : not ( . no - label ) { flex - direction : column ; text - align : center } . opt - btn . align - vertical : not ( . no - label ) . opt - btn - text - wrapper { margin - top : 4 px } . opt - btn . align - vertical : not ( . no - label ) . opt - btn - label { font - size : 12 px ; line - height : 1.2 } . opt - btn . align - horizontal : not ( . no - label ) { flex - direction : row } . opt - btn . align - horizontal : not ( . no - label ) . opt - btn - text - wrapper { margin - left : 8 px } . opt - btn . align - horizontal : not ( . no - label ) . opt - btn - label { font - size : 14 px } . opt - btn . no - label . opt - btn - text - wrapper { width : 0 ; height : 0 ; margin : 0 ; padding : 0 ; overflow : visible ; position : absolute ; top : 0 ; right : 0 } . opt - btn . no - label . opt - btn - arrow { position : absolute ; top : 2 px ; right : 2 px ; margin : 0 ; font - size : 8 px } . opt - btn - dropdown { position : absolute ; background - color : var ( -- bim - toolbar - bg , rgba ( 17 , 17 , 17 , . 95 ) ) ; border - radius : 4 px ; padding : 4 px ; box - shadow : 0 4 px 12 px # 0003 ; z - index : 1001 ; display : flex ; flex - direction : column ; border : 1 px solid rgba ( 255 , 255 , 255 , . 1 ) ; opacity : 0 ; visibility : hidden ; transform : translateY ( - 10 px ) ; transition : opacity . 2 s ease , transform . 2 s cubic - bezier ( . 2 , 0 , . 2 , 1 ) , visibility . 2 s } @ keyframes dropdown - fade - in { 0 % { opacity : 0 ; transform : translateY ( - 8 px ) scale ( . 98 ) } to { opacity : 1 ; transform : translateY ( 0 ) scale ( 1 ) } } . opt - btn - dropdown { animation : dropdown - fade - in . 2 s cubic - bezier ( . 2 , 0 , . 2 , 1 ) forwards ; opacity : 1 ; visibility : visible ; transform : none } . opt - btn - dropdown - item { display : flex ; align - items : center ; padding : 8 px 12 px ; cursor : pointer ; border - radius : 4 px ; color : var ( -- bim - btn - text - color , # ccc ) ; transition : background . 2 s , border - color . 2 s , color . 2 s ; box - sizing : border - box ; border : 1 px solid transparent ; outline : none } . opt - btn - dropdown - item . opt - btn - icon { color : var ( -- bim - icon - color , # ccc ) } . opt - btn - dropdown - item : hover { background - color : var ( -- bim - btn - hover - bg , # 444 ) } . opt - btn - dropdown - item . active { background - color : var ( -- bim - btn - active - bg , rgba ( 255 , 255 , 255 , . 15 ) ) ; color : var ( -- bim - btn - text - active - color , # fff ) } .
2026-01-28 18:40:46 +08:00
( function ( Bs , Hr ) { typeof exports == "object" && typeof module < "u" ? Hr ( exports ) : typeof define == "function" && define . amd ? define ( [ "exports" ] , Hr ) : ( Bs = typeof globalThis < "u" ? globalThis : Bs || self , Hr ( Bs . IflowEngine = { } ) ) } ) ( this , ( function ( Bs ) { "use strict" ; const Hr = { common : { title : "BimEngine" , description : "这是一个使用 BIM-ENGINE。" , openTestDialog : "打开测试弹窗" , openInfoDialog : "打开信息弹窗 (封装版)" } , toolbar : { home : "首页" , measure : "测量" , zoomBox : "选框放大" , info : "信息" , location : "定位" , setting : "设置" , walk : "漫游" , map : "地图" , property : "构件详情" , fullscreen : "全屏" , walkMenu : "漫游菜单" , walkPerson : "第一人称" , walkBird : "第三人称" , tree : "模型树" , section : "剖切" , sectionPlane : "拾取面剖切" , sectionAxis : "轴向剖切" , sectionBox : "剖切盒" } , dialog : { testTitle : "测试弹窗" , testContent : '<div style="padding: 10px;">这是一个 <b>可拖拽</b> 且 <b>可缩放</b> 的弹窗。<br><br>你可以尝试拖动标题栏,或者拖动右下角改变大小。</div>' } , menu : { info : "信息" , home : "首页" , componentDetail : "构件详情" , hideSelected : "隐藏选中构件" , transparentSelected : "半透明选中构件" , isolateSelected : "隔离选中构件" , hideOthers : "其他构件隐藏" , transparentOthers : "其他构件半透明" , fitSectionBox : "剖切盒适应" , showAll : "显示全部" } , tree : { searchPlaceholder : "请输入要搜索的内容" } , constructTree : { title : "目录树" } , tab : { component : "构件" , system : "系统" , space : "空间" , type : "类型" , major : "专业" } , panel : { property : { title : "构件详情" , base : "基本属性" , material : "材质信息" , advanced : "高级设置" , tab : { props : "属性" , material : "材质" } } , componentDetail : { title : "构件详情" , noSelection : "请先选中构件" } } , measure : { btnName : "测量" , dialogTitle : "测量" , modes : { distance : "距离" , minDistance : "最小距离" , angle : "角度" , elevation : "标高" , volume : "体积" , laserDistance : "激光测距" , slope : "坡度" , spaceVolume : "空间体积" } , actions : { expand : "展开" , collapse : "收起" , clearAll : "删除全部" , settings : "设置" } , labels : { currentMode : "当前测量方式:" , x : "X: " , y : "Y: " , z : "Z: " , value : { distance : "距离:" , minDistance : "最小距离:" , angle : "角度:" , elevation : "标高:" , volume : "体积:" , laserDistance : "激光测距:" , slope : "坡度:" , spaceVolume : "空间体积:" } } , units : { mm : "mm" , cm : "cm" , m : "m" , km : "km" , deg : "°" , m3 : "m³" , percent : "%" } , settings : { title : "设置" , unit : "单位:" , precision : "精度:" , hint : "距离、最小距离和标高默认使用该单位;角度和体积有各自默认单位。" , save : "保存设置" , cancel : "取消" } } , sectionPlane : { dialogTitle : "拾取面剖切" , actions : { hide : "隐藏" , reverse : "反向" , reset : "重置" } } , sectionAxis : { dialogTitle : "轴向剖切" , actions : { hide : "隐藏" , reverse : "反向" , axisX : "X" , axisY : "Y" , axisZ : "Z" } } , sectionBox : { dialogTitle : "剖切盒" , actions : { hide : "隐藏" , reverse : "反向" , fitToModel : "适应" , reset : "重置" } , axes : { x : "X" , y : "Y" , z : "Z" } } , walkControl : { speed : "移动速度:" , gravity : "重力" , collision : "碰撞" , characterModel : { label : "建筑工人" , constructionWorker : "建筑工人" , officeMale : "办公室男性" } , walkMode : { label : "行走模式" , walk : "行走模式" , run : "奔跑模式" } , exit : "退出" , path : { dialogTitle : "路径漫游" } } , map : { dialogTitle : "地图" } } , Y0 = { common : { title : "BimEngine" , description : "This is a BIM-ENGINE demo." , openTestDialog : "Open Test Dialog" , openInfoDialog : "Open Info Dialog (Wrapped)" } , toolbar : { home : "Home" , measure : "Measure" , zoomBox : "Zoom Box" , info : "Info" , location : "Location" , setting : "Settings" , walk : "Walk" , map : "Map" , property : "Property" , fullscreen : "Fullscreen" , walkPerson : "Person" , walkBird : "Bird Eye" , walkMenu : "Menu" , tree : "Tree" , section : "Section" , sectionPlane : "Plane Section" , sectionAxis : "Axis Section" , sectionBox : "Section Box" } , dialog : { testTitle : "Test Dialog" , testContent : '<div style="padding: 10px;">This is a <b>draggable</b> and <b>resizable</b> dialog.<br><br>Try dragging the title bar or resizing from the bottom-right corner.</div>' } , menu : { info : "Info" , home : "Home" , componentDetail : "Component Detail" , hideSelected : "Hide Selected" , transparentSelected : "Transparent Selected" , isolateSelected : " Isolate Se
2026-01-22 11:29:51 +08:00
< li > < strong > Name : < / s t r o n g > S a m p l e P r o j e c t < / l i >
< li > < strong > Version : < / s t r o n g > 1 . 0 . 0 < / l i >
< li > < strong > Date : < / s t r o n g > $ { n e w D a t e ( ) . t o L o c a l e D a t e S t r i n g ( ) } < / l i >
< li > < strong > Status : < / s t r o n g > < s p a n s t y l e = " c o l o r : g r e e n ; " > A c t i v e < / s p a n > < / l i >
2026-01-28 18:40:46 +08:00
` ;const r=document.createElement("button");r.textContent="Update Status",r.style.marginTop="10px",r.onclick=()=>{alert("Status updated!")},t.appendChild(n),t.appendChild(i),t.appendChild(r),super({container:e,title:"dialog.testTitle",content:t,width:320,height:"auto",position:"center",resizable:!0,draggable:!0,onClose:()=>{console.log("Info dialog closed")},onOpen:()=>{console.log("Info dialog opened")}})}}class sg extends pi{container;activeDialogs=[];constructor(e){super(),this.container=e,this.subscribe("ui:open-dialog",t=>{console.log("[DialogManager] Received open-dialog event:",t),t.id==="info"&&this.showInfoDialog()})}create(e){const t=new sd({container:this.container,...e,onClose:()=>{this.activeDialogs=this.activeDialogs.filter(n=>n!==t),e.onClose&&e.onClose()}});return t.setTheme(rt.getTheme()),this.activeDialogs.push(t),t}showInfoDialog(){new ig(this.container)}updateTheme(e){this.activeDialogs.forEach(t=>{t.setTheme&&t.setTheme(e)})}destroy(){this.activeDialogs.forEach(e=>e.destroy()),this.activeDialogs=[],super.destroy()}}const Vr="181",Ns={ROTATE:0,DOLLY:1,PAN:2},Us={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},rg=0,rd=1,og=2,od=1,ad=2,mi=3,Pn=0,on=1,Et=2,Wt=0,Os=1,Hl=2,ld=3,cd=4,hd=5,Gn=100,ag=101,lg=102,cg=103,hg=104,Gr=200,ug=201,dg=202,fg=203,Vl=204,Gl=205,Wl=206,pg=207,Xl=208,mg=209,gg=210,xg=211,vg=212,bg=213,yg=214,jl=0,Zl=1,ql=2,ks=3,Yl=4,Kl=5, $ l=6,Jl=7,Wo=0,_g=1,Mg=2,Ni=0,ud=1,dd=2,fd=3,Ql=4,pd=5,md=6,gd=7,xd="attached",wg="detached",vd=300,Fs=301,zs=302,ec=303,tc=304,Xo=306,ni=1e3,ii=1001,jo=1002,Kt=1003,bd=1004,Wr=1005, $ t=1006,Zo=1007,gi=1008,Wn=1009,yd=1010,_d=1011,Xr=1012,nc=1013,ts=1014,Xn=1015,Rn=1016,ic=1017,sc=1018,Hs=1020,Md=35902,wd=35899,Sd=1021,Ed=1022,fn=1023,jr=1026,Vs=1027,rc=1028,oc=1029,ac=1030,lc=1031,cc=1033,qo=33776,Yo=33777,Ko=33778, $ o=33779,hc=35840,uc=35841,dc=35842,fc=35843,pc=36196,mc=37492,gc=37496,xc=37808,vc=37809,bc=37810,yc=37811,_c=37812,Mc=37813,wc=37814,Sc=37815,Ec=37816,Tc=37817,Ac=37818,Cc=37819,Pc=37820,Rc=37821,Lc=36492,Dc=36494,Ic=36495,Bc=36283,Nc=36284,Uc=36285,Oc=36286,Zr=2300,qr=2301,kc=2302,Td=2400,Ad=2401,Cd=2402,Sg=2500,Eg=0,Pd=1,Fc=2,Tg=3200,Ag=3201,Yr=0,Cg=1,Ui="",gt="srgb",Pt="srgb-linear",Jo="linear",lt="srgb",Gs=7680,Rd=519,Pg=512,Rg=513,Lg=514,Ld=515,Dg=516,Ig=517,Bg=518,Ng=519,zc=35044,Dd="300 es",si=2e3,Qo=2001;function Id(s){for(let e=s.length-1;e>=0;--e)if(s[e]>=65535)return!0;return!1}function Kr(s){return document.createElementNS("http://www.w3.org/1999/xhtml",s)}function Ug(){const s=Kr("canvas");return s.style.display="block",s}const Bd={};function ea(...s){const e="THREE."+s.shift();console.log(e,...s)}function He(...s){const e="THREE."+s.shift();console.warn(e,...s)}function Qe(...s){const e="THREE."+s.shift();console.error(e,...s)}function $ r(...s){const e=s.join(" ");e in Bd||(Bd[e]=!0,He(...s))}function Og(s,e,t){return new Promise(function(n,i){function r(){switch(s.clientWaitSync(e,s.SYNC_FLUSH_COMMANDS_BIT,0)){case s.WAIT_FAILED:i();break;case s.TIMEOUT_EXPIRED:setTimeout(r,t);break;default:n()}}setTimeout(r,t)})}class ns{addEventListener(e,t){this._listeners===void 0&&(this._listeners={});const n=this._listeners;n[e]===void 0&&(n[e]=[]),n[e].indexOf(t)===-1&&n[e].push(t)}hasEventListener(e,t){const n=this._listeners;return n===void 0?!1:n[e]!==void 0&&n[e].indexOf(t)!==-1}removeEventListener(e,t){const n=this._listeners;if(n===void 0)return;const i=n[e];if(i!==void 0){const r=i.indexOf(t);r!==-1&&i.splice(r,1)}}dispatchEvent(e){const t=this._listeners;if(t===void 0)return;const n=t[e.type];if(n!==void 0){e.target=this;const i=n.slice(0);for(let r=0,o=i.length;r<o;r++)i[r].call(this,e);e.target=null}}}const en=["00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f","10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f","20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f","30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f","40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f","50","51","52","53","5
2026-01-22 11:29:51 +08:00
gl _Position = projectionMatrix * modelViewMatrix * vec4 ( position , 1.0 ) ;
2026-01-28 17:19:36 +08:00
} ` ,bx= ` void main ( ) {
2026-01-22 11:29:51 +08:00
gl _FragColor = vec4 ( 1.0 , 0.0 , 0.0 , 1.0 ) ;
2026-01-28 18:40:46 +08:00
} ` ;class Ut extends gn{constructor(e){super(),this.isShaderMaterial=!0,this.type="ShaderMaterial",this.defines={},this.uniforms={},this.uniformsGroups=[],this.vertexShader=vx,this.fragmentShader=bx,this.linewidth=1,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.clipping=!1,this.forceSinglePass=!0,this.extensions={clipCullDistance:!1,multiDraw:!1},this.defaultAttributeValues={color:[1,1,1],uv:[0,0],uv1:[0,0]},this.index0AttributeName=void 0,this.uniformsNeedUpdate=!1,this.glslVersion=null,e!==void 0&&this.setValues(e)}copy(e){return super.copy(e),this.fragmentShader=e.fragmentShader,this.vertexShader=e.vertexShader,this.uniforms=nr(e.uniforms),this.uniformsGroups=xx(e.uniformsGroups),this.defines=Object.assign({},e.defines),this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.fog=e.fog,this.lights=e.lights,this.clipping=e.clipping,this.extensions=Object.assign({},e.extensions),this.glslVersion=e.glslVersion,this}toJSON(e){const t=super.toJSON(e);t.glslVersion=this.glslVersion,t.uniforms={};for(const i in this.uniforms){const o=this.uniforms[i].value;o&&o.isTexture?t.uniforms[i]={type:"t",value:o.toJSON(e).uuid}:o&&o.isColor?t.uniforms[i]={type:"c",value:o.getHex()}:o&&o.isVector2?t.uniforms[i]={type:"v2",value:o.toArray()}:o&&o.isVector3?t.uniforms[i]={type:"v3",value:o.toArray()}:o&&o.isVector4?t.uniforms[i]={type:"v4",value:o.toArray()}:o&&o.isMatrix3?t.uniforms[i]={type:"m3",value:o.toArray()}:o&&o.isMatrix4?t.uniforms[i]={type:"m4",value:o.toArray()}:t.uniforms[i]={value:o}}Object.keys(this.defines).length>0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t.lights=this.lights,t.clipping=this.clipping;const n={};for(const i in this.extensions)this.extensions[i]===!0&&(n[i]=!0);return Object.keys(n).length>0&&(t.extensions=n),t}}class tf extends wt{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new ke,this.projectionMatrix=new ke,this.projectionMatrixInverse=new ke,this.coordinateSystem=si,this._reversedDepth=!1}get reversedDepth(){return this._reversedDepth}copy(e,t){return super.copy(e,t),this.matrixWorldInverse.copy(e.matrixWorldInverse),this.projectionMatrix.copy(e.projectionMatrix),this.projectionMatrixInverse.copy(e.projectionMatrixInverse),this.coordinateSystem=e.coordinateSystem,this}getWorldDirection(e){return super.getWorldDirection(e).negate()}updateMatrixWorld(e){super.updateMatrixWorld(e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(e,t){super.updateWorldMatrix(e,t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return new this.constructor().copy(this)}}const Wi=new P,nf=new ce,sf=new ce;class sn extends tf{constructor(e=50,t=1,n=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=e,this.zoom=1,this.near=n,this.far=i,this.focus=10,this.aspect=t,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.fov=e.fov,this.zoom=e.zoom,this.near=e.near,this.far=e.far,this.focus=e.focus,this.aspect=e.aspect,this.view=e.view===null?null:Object.assign({},e.view),this.filmGauge=e.filmGauge,this.filmOffset=e.filmOffset,this}setFocalLength(e){const t=.5*this.getFilmHeight()/e;this.fov=Ws*2*Math.atan(t),this.updateProjectionMatrix()}getFocalLength(){const e=Math.tan(Jr*.5*this.fov);return .5*this.getFilmHeight()/e}getEffectiveFOV(){return Ws*2*Math.atan(Math.tan(Jr*.5*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(e,t,n){Wi.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),t.set(Wi.x,Wi.y).multiplyScalar(-e/Wi.z),Wi.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),n.set(Wi.x,Wi.y).multiplyScalar(-e/Wi.z)}getViewSize(e,t){return this.getViewBounds(e,nf,sf),t.subVectors(sf,nf)}setViewOffset(e,t,n,i,r,o){this.aspect=e/t,this.view===null&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.vie
2026-01-22 11:29:51 +08:00
varying vec3 vWorldDirection ;
vec3 transformDirection ( in vec3 dir , in mat4 matrix ) {
return normalize ( ( matrix * vec4 ( dir , 0.0 ) ) . xyz ) ;
}
void main ( ) {
vWorldDirection = transformDirection ( position , modelMatrix ) ;
# include < begin _vertex >
# include < project _vertex >
}
` ,fragmentShader: `
uniform sampler2D tEquirect ;
varying vec3 vWorldDirection ;
# include < common >
void main ( ) {
vec3 direction = normalize ( vWorldDirection ) ;
vec2 sampleUV = equirectUv ( direction ) ;
gl _FragColor = texture2D ( tEquirect , sampleUV ) ;
}
2026-01-28 18:40:46 +08:00
` },i=new Gi(5,5,5),r=new Ut({name:"CubemapFromEquirect",uniforms:nr(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:on,blending:Wt});r.uniforms.tEquirect.value=t;const o=new ut(i,r),a=t.minFilter;return t.minFilter===gi&&(t.minFilter= $ t),new yx(1,10,this).update(e,o),t.minFilter=a,o.geometry.dispose(),o.material.dispose(),this}clear(e,t=!0,n=!0,i=!0){const r=e.getRenderTarget();for(let o=0;o<6;o++)e.setRenderTarget(this,o),e.clear(t,n,i);e.setRenderTarget(r)}}class xn extends wt{constructor(){super(),this.isGroup=!0,this.type="Group"}}const Mx={type:"move"};class hh{constructor(){this._targetRay=null,this._grip=null,this._hand=null}getHandSpace(){return this._hand===null&&(this._hand=new xn,this._hand.matrixAutoUpdate=!1,this._hand.visible=!1,this._hand.joints={},this._hand.inputState={pinching:!1}),this._hand}getTargetRaySpace(){return this._targetRay===null&&(this._targetRay=new xn,this._targetRay.matrixAutoUpdate=!1,this._targetRay.visible=!1,this._targetRay.hasLinearVelocity=!1,this._targetRay.linearVelocity=new P,this._targetRay.hasAngularVelocity=!1,this._targetRay.angularVelocity=new P),this._targetRay}getGripSpace(){return this._grip===null&&(this._grip=new xn,this._grip.matrixAutoUpdate=!1,this._grip.visible=!1,this._grip.hasLinearVelocity=!1,this._grip.linearVelocity=new P,this._grip.hasAngularVelocity=!1,this._grip.angularVelocity=new P),this._grip}dispatchEvent(e){return this._targetRay!==null&&this._targetRay.dispatchEvent(e),this._grip!==null&&this._grip.dispatchEvent(e),this._hand!==null&&this._hand.dispatchEvent(e),this}connect(e){if(e&&e.hand){const t=this._hand;if(t)for(const n of e.hand.values())this._getHandJoint(t,n)}return this.dispatchEvent({type:"connected",data:e}),this}disconnect(e){return this.dispatchEvent({type:"disconnected",data:e}),this._targetRay!==null&&(this._targetRay.visible=!1),this._grip!==null&&(this._grip.visible=!1),this._hand!==null&&(this._hand.visible=!1),this}update(e,t,n){let i=null,r=null,o=null;const a=this._targetRay,l=this._grip,c=this._hand;if(e&&t.session.visibilityState!=="visible-blurred"){if(c&&e.hand){o=!0;for(const p of e.hand.values()){const x=t.getJointPose(p,n),m=this._getHandJoint(c,p);x!==null&&(m.matrix.fromArray(x.transform.matrix),m.matrix.decompose(m.position,m.rotation,m.scale),m.matrixWorldNeedsUpdate=!0,m.jointRadius=x.radius),m.visible=x!==null}const h=c.joints["index-finger-tip"],u=c.joints["thumb-tip"],d=h.position.distanceTo(u.position),f=.02,g=.005;c.inputState.pinching&&d>f+g?(c.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:e.handedness,target:this})):!c.inputState.pinching&&d<=f-g&&(c.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:e.handedness,target:this}))}else l!==null&&e.gripSpace&&(r=t.getPose(e.gripSpace,n),r!==null&&(l.matrix.fromArray(r.transform.matrix),l.matrix.decompose(l.position,l.rotation,l.scale),l.matrixWorldNeedsUpdate=!0,r.linearVelocity?(l.hasLinearVelocity=!0,l.linearVelocity.copy(r.linearVelocity)):l.hasLinearVelocity=!1,r.angularVelocity?(l.hasAngularVelocity=!0,l.angularVelocity.copy(r.angularVelocity)):l.hasAngularVelocity=!1));a!==null&&(i=t.getPose(e.targetRaySpace,n),i===null&&r!==null&&(i=r),i!==null&&(a.matrix.fromArray(i.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale),a.matrixWorldNeedsUpdate=!0,i.linearVelocity?(a.hasLinearVelocity=!0,a.linearVelocity.copy(i.linearVelocity)):a.hasLinearVelocity=!1,i.angularVelocity?(a.hasAngularVelocity=!0,a.angularVelocity.copy(i.angularVelocity)):a.hasAngularVelocity=!1,this.dispatchEvent(Mx)))}return a!==null&&(a.visible=i!==null),l!==null&&(l.visible=r!==null),c!==null&&(c.visible=o!==null),this}_getHandJoint(e,t){if(e.joints[t.jointName]===void 0){const n=new xn;n.matrixAutoUpdate=!1,n.visible=!1,e.joints[t.jointName]=n,e.add(n)}return e.joints[t.jointName]}}class of extends wt{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new mn,thi
2026-01-22 11:29:51 +08:00
if ( diffuseColor . a < getAlphaHashThreshold ( vPosition ) ) discard ;
2026-01-28 17:19:36 +08:00
# endif ` ,Qv= ` # ifdef USE _ALPHAHASH
2026-01-22 11:29:51 +08:00
const float ALPHA _HASH _SCALE = 0.05 ;
float hash2D ( vec2 value ) {
return fract ( 1.0 e4 * sin ( 17.0 * value . x + 0.1 * value . y ) * ( 0.1 + abs ( sin ( 13.0 * value . y + value . x ) ) ) ) ;
}
float hash3D ( vec3 value ) {
return hash2D ( vec2 ( hash2D ( value . xy ) , value . z ) ) ;
}
float getAlphaHashThreshold ( vec3 position ) {
float maxDeriv = max (
length ( dFdx ( position . xyz ) ) ,
length ( dFdy ( position . xyz ) )
) ;
float pixScale = 1.0 / ( ALPHA _HASH _SCALE * maxDeriv ) ;
vec2 pixScales = vec2 (
exp2 ( floor ( log2 ( pixScale ) ) ) ,
exp2 ( ceil ( log2 ( pixScale ) ) )
) ;
vec2 alpha = vec2 (
hash3D ( floor ( pixScales . x * position . xyz ) ) ,
hash3D ( floor ( pixScales . y * position . xyz ) )
) ;
float lerpFactor = fract ( log2 ( pixScale ) ) ;
float x = ( 1.0 - lerpFactor ) * alpha . x + lerpFactor * alpha . y ;
float a = min ( lerpFactor , 1.0 - lerpFactor ) ;
vec3 cases = vec3 (
x * x / ( 2.0 * a * ( 1.0 - a ) ) ,
( x - 0.5 * a ) / ( 1.0 - a ) ,
1.0 - ( ( 1.0 - x ) * ( 1.0 - x ) / ( 2.0 * a * ( 1.0 - a ) ) )
) ;
float threshold = ( x < ( 1.0 - a ) )
? ( ( x < a ) ? cases . x : cases . y )
: cases . z ;
return clamp ( threshold , 1.0 e - 6 , 1.0 ) ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,e1= ` # ifdef USE _ALPHAMAP
2026-01-22 11:29:51 +08:00
diffuseColor . a *= texture2D ( alphaMap , vAlphaMapUv ) . g ;
2026-01-28 17:19:36 +08:00
# endif ` ,t1= ` # ifdef USE _ALPHAMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D alphaMap ;
2026-01-28 17:19:36 +08:00
# endif ` ,n1= ` # ifdef USE _ALPHATEST
2026-01-22 11:29:51 +08:00
# ifdef ALPHA _TO _COVERAGE
diffuseColor . a = smoothstep ( alphaTest , alphaTest + fwidth ( diffuseColor . a ) , diffuseColor . a ) ;
if ( diffuseColor . a == 0.0 ) discard ;
# else
if ( diffuseColor . a < alphaTest ) discard ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,i1= ` # ifdef USE _ALPHATEST
2026-01-22 11:29:51 +08:00
uniform float alphaTest ;
2026-01-28 17:19:36 +08:00
# endif ` ,s1= ` # ifdef USE _AOMAP
2026-01-22 11:29:51 +08:00
float ambientOcclusion = ( texture2D ( aoMap , vAoMapUv ) . r - 1.0 ) * aoMapIntensity + 1.0 ;
reflectedLight . indirectDiffuse *= ambientOcclusion ;
# if defined ( USE _CLEARCOAT )
clearcoatSpecularIndirect *= ambientOcclusion ;
# endif
# if defined ( USE _SHEEN )
sheenSpecularIndirect *= ambientOcclusion ;
# endif
# if defined ( USE _ENVMAP ) && defined ( STANDARD )
float dotNV = saturate ( dot ( geometryNormal , geometryViewDir ) ) ;
reflectedLight . indirectSpecular *= computeSpecularOcclusion ( dotNV , ambientOcclusion , material . roughness ) ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,r1= ` # ifdef USE _AOMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D aoMap ;
uniform float aoMapIntensity ;
2026-01-28 17:19:36 +08:00
# endif ` ,o1= ` # ifdef USE _BATCHING
2026-01-22 11:29:51 +08:00
# if ! defined ( GL _ANGLE _multi _draw )
# define gl _DrawID _gl _DrawID
uniform int _gl _DrawID ;
# endif
uniform highp sampler2D batchingTexture ;
uniform highp usampler2D batchingIdTexture ;
mat4 getBatchingMatrix ( const in float i ) {
int size = textureSize ( batchingTexture , 0 ) . x ;
int j = int ( i ) * 4 ;
int x = j % size ;
int y = j / size ;
vec4 v1 = texelFetch ( batchingTexture , ivec2 ( x , y ) , 0 ) ;
vec4 v2 = texelFetch ( batchingTexture , ivec2 ( x + 1 , y ) , 0 ) ;
vec4 v3 = texelFetch ( batchingTexture , ivec2 ( x + 2 , y ) , 0 ) ;
vec4 v4 = texelFetch ( batchingTexture , ivec2 ( x + 3 , y ) , 0 ) ;
return mat4 ( v1 , v2 , v3 , v4 ) ;
}
float getIndirectIndex ( const in int i ) {
int size = textureSize ( batchingIdTexture , 0 ) . x ;
int x = i % size ;
int y = i / size ;
return float ( texelFetch ( batchingIdTexture , ivec2 ( x , y ) , 0 ) . r ) ;
}
# endif
# ifdef USE _BATCHING _COLOR
uniform sampler2D batchingColorTexture ;
vec3 getBatchingColor ( const in float i ) {
int size = textureSize ( batchingColorTexture , 0 ) . x ;
int j = int ( i ) ;
int x = j % size ;
int y = j / size ;
return texelFetch ( batchingColorTexture , ivec2 ( x , y ) , 0 ) . rgb ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,a1= ` # ifdef USE _BATCHING
2026-01-22 11:29:51 +08:00
mat4 batchingMatrix = getBatchingMatrix ( getIndirectIndex ( gl _DrawID ) ) ;
2026-01-28 17:19:36 +08:00
# endif ` ,l1= ` vec3 transformed = vec3 ( position ) ;
2026-01-22 11:29:51 +08:00
# ifdef USE _ALPHAHASH
vPosition = vec3 ( position ) ;
2026-01-28 17:19:36 +08:00
# endif ` ,c1= ` vec3 objectNormal = vec3 ( normal ) ;
2026-01-22 11:29:51 +08:00
# ifdef USE _TANGENT
vec3 objectTangent = vec3 ( tangent . xyz ) ;
2026-01-28 17:19:36 +08:00
# endif ` ,h1= ` float G _BlinnPhong _Implicit ( ) {
2026-01-22 11:29:51 +08:00
return 0.25 ;
}
float D _BlinnPhong ( const in float shininess , const in float dotNH ) {
return RECIPROCAL _PI * ( shininess * 0.5 + 1.0 ) * pow ( dotNH , shininess ) ;
}
vec3 BRDF _BlinnPhong ( const in vec3 lightDir , const in vec3 viewDir , const in vec3 normal , const in vec3 specularColor , const in float shininess ) {
vec3 halfDir = normalize ( lightDir + viewDir ) ;
float dotNH = saturate ( dot ( normal , halfDir ) ) ;
float dotVH = saturate ( dot ( viewDir , halfDir ) ) ;
vec3 F = F _Schlick ( specularColor , 1.0 , dotVH ) ;
float G = G _BlinnPhong _Implicit ( ) ;
float D = D _BlinnPhong ( shininess , dotNH ) ;
return F * ( G * D ) ;
2026-01-28 17:19:36 +08:00
} // validated`,u1=`#ifdef USE_IRIDESCENCE
2026-01-22 11:29:51 +08:00
const mat3 XYZ _TO _REC709 = mat3 (
3.2404542 , - 0.9692660 , 0.0556434 ,
- 1.5371385 , 1.8760108 , - 0.2040259 ,
- 0.4985314 , 0.0415560 , 1.0572252
) ;
vec3 Fresnel0ToIor ( vec3 fresnel0 ) {
vec3 sqrtF0 = sqrt ( fresnel0 ) ;
return ( vec3 ( 1.0 ) + sqrtF0 ) / ( vec3 ( 1.0 ) - sqrtF0 ) ;
}
vec3 IorToFresnel0 ( vec3 transmittedIor , float incidentIor ) {
return pow2 ( ( transmittedIor - vec3 ( incidentIor ) ) / ( transmittedIor + vec3 ( incidentIor ) ) ) ;
}
float IorToFresnel0 ( float transmittedIor , float incidentIor ) {
return pow2 ( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ) ) ;
}
vec3 evalSensitivity ( float OPD , vec3 shift ) {
float phase = 2.0 * PI * OPD * 1.0 e - 9 ;
vec3 val = vec3 ( 5.4856 e - 13 , 4.4201 e - 13 , 5.2481 e - 13 ) ;
vec3 pos = vec3 ( 1.6810 e + 06 , 1.7953 e + 06 , 2.2084 e + 06 ) ;
vec3 var = vec3 ( 4.3278 e + 09 , 9.3046 e + 09 , 6.6121 e + 09 ) ;
vec3 xyz = val * sqrt ( 2.0 * PI * var ) * cos ( pos * phase + shift ) * exp ( - pow2 ( phase ) * var ) ;
xyz . x += 9.7470 e - 14 * sqrt ( 2.0 * PI * 4.5282 e + 09 ) * cos ( 2.2399 e + 06 * phase + shift [ 0 ] ) * exp ( - 4.5282 e + 09 * pow2 ( phase ) ) ;
xyz /= 1.0685 e - 7 ;
vec3 rgb = XYZ _TO _REC709 * xyz ;
return rgb ;
}
vec3 evalIridescence ( float outsideIOR , float eta2 , float cosTheta1 , float thinFilmThickness , vec3 baseF0 ) {
vec3 I ;
float iridescenceIOR = mix ( outsideIOR , eta2 , smoothstep ( 0.0 , 0.03 , thinFilmThickness ) ) ;
float sinTheta2Sq = pow2 ( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2 ( cosTheta1 ) ) ;
float cosTheta2Sq = 1.0 - sinTheta2Sq ;
if ( cosTheta2Sq < 0.0 ) {
return vec3 ( 1.0 ) ;
}
float cosTheta2 = sqrt ( cosTheta2Sq ) ;
float R0 = IorToFresnel0 ( iridescenceIOR , outsideIOR ) ;
float R12 = F _Schlick ( R0 , 1.0 , cosTheta1 ) ;
float T121 = 1.0 - R12 ;
float phi12 = 0.0 ;
if ( iridescenceIOR < outsideIOR ) phi12 = PI ;
float phi21 = PI - phi12 ;
vec3 baseIOR = Fresnel0ToIor ( clamp ( baseF0 , 0.0 , 0.9999 ) ) ; vec3 R1 = IorToFresnel0 ( baseIOR , iridescenceIOR ) ;
vec3 R23 = F _Schlick ( R1 , 1.0 , cosTheta2 ) ;
vec3 phi23 = vec3 ( 0.0 ) ;
if ( baseIOR [ 0 ] < iridescenceIOR ) phi23 [ 0 ] = PI ;
if ( baseIOR [ 1 ] < iridescenceIOR ) phi23 [ 1 ] = PI ;
if ( baseIOR [ 2 ] < iridescenceIOR ) phi23 [ 2 ] = PI ;
float OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2 ;
vec3 phi = vec3 ( phi21 ) + phi23 ;
vec3 R123 = clamp ( R12 * R23 , 1e-5 , 0.9999 ) ;
vec3 r123 = sqrt ( R123 ) ;
vec3 Rs = pow2 ( T121 ) * R23 / ( vec3 ( 1.0 ) - R123 ) ;
vec3 C0 = R12 + Rs ;
I = C0 ;
vec3 Cm = Rs - T121 ;
for ( int m = 1 ; m <= 2 ; ++ m ) {
Cm *= r123 ;
vec3 Sm = 2.0 * evalSensitivity ( float ( m ) * OPD , float ( m ) * phi ) ;
I += Cm * Sm ;
}
return max ( I , vec3 ( 0.0 ) ) ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,d1= ` # ifdef USE _BUMPMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D bumpMap ;
uniform float bumpScale ;
vec2 dHdxy _fwd ( ) {
vec2 dSTdx = dFdx ( vBumpMapUv ) ;
vec2 dSTdy = dFdy ( vBumpMapUv ) ;
float Hll = bumpScale * texture2D ( bumpMap , vBumpMapUv ) . x ;
float dBx = bumpScale * texture2D ( bumpMap , vBumpMapUv + dSTdx ) . x - Hll ;
float dBy = bumpScale * texture2D ( bumpMap , vBumpMapUv + dSTdy ) . x - Hll ;
return vec2 ( dBx , dBy ) ;
}
vec3 perturbNormalArb ( vec3 surf _pos , vec3 surf _norm , vec2 dHdxy , float faceDirection ) {
vec3 vSigmaX = normalize ( dFdx ( surf _pos . xyz ) ) ;
vec3 vSigmaY = normalize ( dFdy ( surf _pos . xyz ) ) ;
vec3 vN = surf _norm ;
vec3 R1 = cross ( vSigmaY , vN ) ;
vec3 R2 = cross ( vN , vSigmaX ) ;
float fDet = dot ( vSigmaX , R1 ) * faceDirection ;
vec3 vGrad = sign ( fDet ) * ( dHdxy . x * R1 + dHdxy . y * R2 ) ;
return normalize ( abs ( fDet ) * surf _norm - vGrad ) ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,f1= ` # if NUM _CLIPPING _PLANES > 0
2026-01-22 11:29:51 +08:00
vec4 plane ;
# ifdef ALPHA _TO _COVERAGE
float distanceToPlane , distanceGradient ;
float clipOpacity = 1.0 ;
# pragma unroll _loop _start
for ( int i = 0 ; i < UNION _CLIPPING _PLANES ; i ++ ) {
plane = clippingPlanes [ i ] ;
distanceToPlane = - dot ( vClipPosition , plane . xyz ) + plane . w ;
distanceGradient = fwidth ( distanceToPlane ) / 2.0 ;
clipOpacity *= smoothstep ( - distanceGradient , distanceGradient , distanceToPlane ) ;
if ( clipOpacity == 0.0 ) discard ;
}
# pragma unroll _loop _end
# if UNION _CLIPPING _PLANES < NUM _CLIPPING _PLANES
float unionClipOpacity = 1.0 ;
# pragma unroll _loop _start
for ( int i = UNION _CLIPPING _PLANES ; i < NUM _CLIPPING _PLANES ; i ++ ) {
plane = clippingPlanes [ i ] ;
distanceToPlane = - dot ( vClipPosition , plane . xyz ) + plane . w ;
distanceGradient = fwidth ( distanceToPlane ) / 2.0 ;
unionClipOpacity *= 1.0 - smoothstep ( - distanceGradient , distanceGradient , distanceToPlane ) ;
}
# pragma unroll _loop _end
clipOpacity *= 1.0 - unionClipOpacity ;
# endif
diffuseColor . a *= clipOpacity ;
if ( diffuseColor . a == 0.0 ) discard ;
# else
# pragma unroll _loop _start
for ( int i = 0 ; i < UNION _CLIPPING _PLANES ; i ++ ) {
plane = clippingPlanes [ i ] ;
if ( dot ( vClipPosition , plane . xyz ) > plane . w ) discard ;
}
# pragma unroll _loop _end
# if UNION _CLIPPING _PLANES < NUM _CLIPPING _PLANES
bool clipped = true ;
# pragma unroll _loop _start
for ( int i = UNION _CLIPPING _PLANES ; i < NUM _CLIPPING _PLANES ; i ++ ) {
plane = clippingPlanes [ i ] ;
clipped = ( dot ( vClipPosition , plane . xyz ) > plane . w ) && clipped ;
}
# pragma unroll _loop _end
if ( clipped ) discard ;
# endif
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,p1= ` # if NUM _CLIPPING _PLANES > 0
2026-01-22 11:29:51 +08:00
varying vec3 vClipPosition ;
uniform vec4 clippingPlanes [ NUM _CLIPPING _PLANES ] ;
2026-01-28 17:19:36 +08:00
# endif ` ,m1= ` # if NUM _CLIPPING _PLANES > 0
2026-01-22 11:29:51 +08:00
varying vec3 vClipPosition ;
2026-01-28 17:19:36 +08:00
# endif ` ,g1= ` # if NUM _CLIPPING _PLANES > 0
2026-01-22 11:29:51 +08:00
vClipPosition = - mvPosition . xyz ;
2026-01-28 17:19:36 +08:00
# endif ` ,x1= ` # if defined ( USE _COLOR _ALPHA )
2026-01-22 11:29:51 +08:00
diffuseColor *= vColor ;
# elif defined ( USE _COLOR )
diffuseColor . rgb *= vColor ;
2026-01-28 17:19:36 +08:00
# endif ` ,v1= ` # if defined ( USE _COLOR _ALPHA )
2026-01-22 11:29:51 +08:00
varying vec4 vColor ;
# elif defined ( USE _COLOR )
varying vec3 vColor ;
2026-01-28 17:19:36 +08:00
# endif ` ,b1= ` # if defined ( USE _COLOR _ALPHA )
2026-01-22 11:29:51 +08:00
varying vec4 vColor ;
# elif defined ( USE _COLOR ) || defined ( USE _INSTANCING _COLOR ) || defined ( USE _BATCHING _COLOR )
varying vec3 vColor ;
2026-01-28 17:19:36 +08:00
# endif ` ,y1= ` # if defined ( USE _COLOR _ALPHA )
2026-01-22 11:29:51 +08:00
vColor = vec4 ( 1.0 ) ;
# elif defined ( USE _COLOR ) || defined ( USE _INSTANCING _COLOR ) || defined ( USE _BATCHING _COLOR )
vColor = vec3 ( 1.0 ) ;
# endif
# ifdef USE _COLOR
vColor *= color ;
# endif
# ifdef USE _INSTANCING _COLOR
vColor . xyz *= instanceColor . xyz ;
# endif
# ifdef USE _BATCHING _COLOR
vec3 batchingColor = getBatchingColor ( getIndirectIndex ( gl _DrawID ) ) ;
vColor . xyz *= batchingColor . xyz ;
2026-01-28 17:19:36 +08:00
# endif ` ,_1= ` # define PI 3.141592653589793
2026-01-22 11:29:51 +08:00
# define PI2 6.283185307179586
# define PI _HALF 1.5707963267948966
# define RECIPROCAL _PI 0.3183098861837907
# define RECIPROCAL _PI2 0.15915494309189535
# define EPSILON 1e-6
# ifndef saturate
# define saturate ( a ) clamp ( a , 0.0 , 1.0 )
# endif
# define whiteComplement ( a ) ( 1.0 - saturate ( a ) )
float pow2 ( const in float x ) { return x * x ; }
vec3 pow2 ( const in vec3 x ) { return x * x ; }
float pow3 ( const in float x ) { return x * x * x ; }
float pow4 ( const in float x ) { float x2 = x * x ; return x2 * x2 ; }
float max3 ( const in vec3 v ) { return max ( max ( v . x , v . y ) , v . z ) ; }
float average ( const in vec3 v ) { return dot ( v , vec3 ( 0.3333333 ) ) ; }
highp float rand ( const in vec2 uv ) {
const highp float a = 12.9898 , b = 78.233 , c = 43758.5453 ;
highp float dt = dot ( uv . xy , vec2 ( a , b ) ) , sn = mod ( dt , PI ) ;
return fract ( sin ( sn ) * c ) ;
}
# ifdef HIGH _PRECISION
float precisionSafeLength ( vec3 v ) { return length ( v ) ; }
# else
float precisionSafeLength ( vec3 v ) {
float maxComponent = max3 ( abs ( v ) ) ;
return length ( v / maxComponent ) * maxComponent ;
}
# endif
struct IncidentLight {
vec3 color ;
vec3 direction ;
bool visible ;
} ;
struct ReflectedLight {
vec3 directDiffuse ;
vec3 directSpecular ;
vec3 indirectDiffuse ;
vec3 indirectSpecular ;
} ;
# ifdef USE _ALPHAHASH
varying vec3 vPosition ;
# endif
vec3 transformDirection ( in vec3 dir , in mat4 matrix ) {
return normalize ( ( matrix * vec4 ( dir , 0.0 ) ) . xyz ) ;
}
vec3 inverseTransformDirection ( in vec3 dir , in mat4 matrix ) {
return normalize ( ( vec4 ( dir , 0.0 ) * matrix ) . xyz ) ;
}
bool isPerspectiveMatrix ( mat4 m ) {
return m [ 2 ] [ 3 ] == - 1.0 ;
}
vec2 equirectUv ( in vec3 dir ) {
float u = atan ( dir . z , dir . x ) * RECIPROCAL _PI2 + 0.5 ;
float v = asin ( clamp ( dir . y , - 1.0 , 1.0 ) ) * RECIPROCAL _PI + 0.5 ;
return vec2 ( u , v ) ;
}
vec3 BRDF _Lambert ( const in vec3 diffuseColor ) {
return RECIPROCAL _PI * diffuseColor ;
}
vec3 F _Schlick ( const in vec3 f0 , const in float f90 , const in float dotVH ) {
float fresnel = exp2 ( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ) ;
return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ) ;
}
float F _Schlick ( const in float f0 , const in float f90 , const in float dotVH ) {
float fresnel = exp2 ( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ) ;
return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ) ;
2026-01-28 17:19:36 +08:00
} // validated`,M1=`#ifdef ENVMAP_TYPE_CUBE_UV
2026-01-22 11:29:51 +08:00
# define cubeUV _minMipLevel 4.0
# define cubeUV _minTileSize 16.0
float getFace ( vec3 direction ) {
vec3 absDirection = abs ( direction ) ;
float face = - 1.0 ;
if ( absDirection . x > absDirection . z ) {
if ( absDirection . x > absDirection . y )
face = direction . x > 0.0 ? 0.0 : 3.0 ;
else
face = direction . y > 0.0 ? 1.0 : 4.0 ;
} else {
if ( absDirection . z > absDirection . y )
face = direction . z > 0.0 ? 2.0 : 5.0 ;
else
face = direction . y > 0.0 ? 1.0 : 4.0 ;
}
return face ;
}
vec2 getUV ( vec3 direction , float face ) {
vec2 uv ;
if ( face == 0.0 ) {
uv = vec2 ( direction . z , direction . y ) / abs ( direction . x ) ;
} else if ( face == 1.0 ) {
uv = vec2 ( - direction . x , - direction . z ) / abs ( direction . y ) ;
} else if ( face == 2.0 ) {
uv = vec2 ( - direction . x , direction . y ) / abs ( direction . z ) ;
} else if ( face == 3.0 ) {
uv = vec2 ( - direction . z , direction . y ) / abs ( direction . x ) ;
} else if ( face == 4.0 ) {
uv = vec2 ( - direction . x , direction . z ) / abs ( direction . y ) ;
} else {
uv = vec2 ( direction . x , direction . y ) / abs ( direction . z ) ;
}
return 0.5 * ( uv + 1.0 ) ;
}
vec3 bilinearCubeUV ( sampler2D envMap , vec3 direction , float mipInt ) {
float face = getFace ( direction ) ;
float filterInt = max ( cubeUV _minMipLevel - mipInt , 0.0 ) ;
mipInt = max ( mipInt , cubeUV _minMipLevel ) ;
float faceSize = exp2 ( mipInt ) ;
highp vec2 uv = getUV ( direction , face ) * ( faceSize - 2.0 ) + 1.0 ;
if ( face > 2.0 ) {
uv . y += faceSize ;
face -= 3.0 ;
}
uv . x += face * faceSize ;
uv . x += filterInt * 3.0 * cubeUV _minTileSize ;
uv . y += 4.0 * ( exp2 ( CUBEUV _MAX _MIP ) - faceSize ) ;
uv . x *= CUBEUV _TEXEL _WIDTH ;
uv . y *= CUBEUV _TEXEL _HEIGHT ;
# ifdef texture2DGradEXT
return texture2DGradEXT ( envMap , uv , vec2 ( 0.0 ) , vec2 ( 0.0 ) ) . rgb ;
# else
return texture2D ( envMap , uv ) . rgb ;
# endif
}
# define cubeUV _r0 1.0
# define cubeUV _m0 - 2.0
# define cubeUV _r1 0.8
# define cubeUV _m1 - 1.0
# define cubeUV _r4 0.4
# define cubeUV _m4 2.0
# define cubeUV _r5 0.305
# define cubeUV _m5 3.0
# define cubeUV _r6 0.21
# define cubeUV _m6 4.0
float roughnessToMip ( float roughness ) {
float mip = 0.0 ;
if ( roughness >= cubeUV _r1 ) {
mip = ( cubeUV _r0 - roughness ) * ( cubeUV _m1 - cubeUV _m0 ) / ( cubeUV _r0 - cubeUV _r1 ) + cubeUV _m0 ;
} else if ( roughness >= cubeUV _r4 ) {
mip = ( cubeUV _r1 - roughness ) * ( cubeUV _m4 - cubeUV _m1 ) / ( cubeUV _r1 - cubeUV _r4 ) + cubeUV _m1 ;
} else if ( roughness >= cubeUV _r5 ) {
mip = ( cubeUV _r4 - roughness ) * ( cubeUV _m5 - cubeUV _m4 ) / ( cubeUV _r4 - cubeUV _r5 ) + cubeUV _m4 ;
} else if ( roughness >= cubeUV _r6 ) {
mip = ( cubeUV _r5 - roughness ) * ( cubeUV _m6 - cubeUV _m5 ) / ( cubeUV _r5 - cubeUV _r6 ) + cubeUV _m5 ;
} else {
mip = - 2.0 * log2 ( 1.16 * roughness ) ; }
return mip ;
}
vec4 textureCubeUV ( sampler2D envMap , vec3 sampleDir , float roughness ) {
float mip = clamp ( roughnessToMip ( roughness ) , cubeUV _m0 , CUBEUV _MAX _MIP ) ;
float mipF = fract ( mip ) ;
float mipInt = floor ( mip ) ;
vec3 color0 = bilinearCubeUV ( envMap , sampleDir , mipInt ) ;
if ( mipF == 0.0 ) {
return vec4 ( color0 , 1.0 ) ;
} else {
vec3 color1 = bilinearCubeUV ( envMap , sampleDir , mipInt + 1.0 ) ;
return vec4 ( mix ( color0 , color1 , mipF ) , 1.0 ) ;
}
}
2026-01-28 17:19:36 +08:00
# endif ` ,w1= ` vec3 transformedNormal = objectNormal ;
2026-01-22 11:29:51 +08:00
# ifdef USE _TANGENT
vec3 transformedTangent = objectTangent ;
# endif
# ifdef USE _BATCHING
mat3 bm = mat3 ( batchingMatrix ) ;
transformedNormal /= vec3 ( dot ( bm [ 0 ] , bm [ 0 ] ) , dot ( bm [ 1 ] , bm [ 1 ] ) , dot ( bm [ 2 ] , bm [ 2 ] ) ) ;
transformedNormal = bm * transformedNormal ;
# ifdef USE _TANGENT
transformedTangent = bm * transformedTangent ;
# endif
# endif
# ifdef USE _INSTANCING
mat3 im = mat3 ( instanceMatrix ) ;
transformedNormal /= vec3 ( dot ( im [ 0 ] , im [ 0 ] ) , dot ( im [ 1 ] , im [ 1 ] ) , dot ( im [ 2 ] , im [ 2 ] ) ) ;
transformedNormal = im * transformedNormal ;
# ifdef USE _TANGENT
transformedTangent = im * transformedTangent ;
# endif
# endif
transformedNormal = normalMatrix * transformedNormal ;
# ifdef FLIP _SIDED
transformedNormal = - transformedNormal ;
# endif
# ifdef USE _TANGENT
transformedTangent = ( modelViewMatrix * vec4 ( transformedTangent , 0.0 ) ) . xyz ;
# ifdef FLIP _SIDED
transformedTangent = - transformedTangent ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,S1= ` # ifdef USE _DISPLACEMENTMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D displacementMap ;
uniform float displacementScale ;
uniform float displacementBias ;
2026-01-28 17:19:36 +08:00
# endif ` ,E1= ` # ifdef USE _DISPLACEMENTMAP
2026-01-22 11:29:51 +08:00
transformed += normalize ( objectNormal ) * ( texture2D ( displacementMap , vDisplacementMapUv ) . x * displacementScale + displacementBias ) ;
2026-01-28 17:19:36 +08:00
# endif ` ,T1= ` # ifdef USE _EMISSIVEMAP
2026-01-22 11:29:51 +08:00
vec4 emissiveColor = texture2D ( emissiveMap , vEmissiveMapUv ) ;
# ifdef DECODE _VIDEO _TEXTURE _EMISSIVE
emissiveColor = sRGBTransferEOTF ( emissiveColor ) ;
# endif
totalEmissiveRadiance *= emissiveColor . rgb ;
2026-01-28 17:19:36 +08:00
# endif ` ,A1= ` # ifdef USE _EMISSIVEMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D emissiveMap ;
2026-01-28 17:19:36 +08:00
# endif ` ,C1="gl_FragColor = linearToOutputTexel( gl_FragColor );",P1= ` vec4 LinearTransferOETF ( in vec4 value ) {
2026-01-22 11:29:51 +08:00
return value ;
}
vec4 sRGBTransferEOTF ( in vec4 value ) {
return vec4 ( mix ( pow ( value . rgb * 0.9478672986 + vec3 ( 0.0521327014 ) , vec3 ( 2.4 ) ) , value . rgb * 0.0773993808 , vec3 ( lessThanEqual ( value . rgb , vec3 ( 0.04045 ) ) ) ) , value . a ) ;
}
vec4 sRGBTransferOETF ( in vec4 value ) {
return vec4 ( mix ( pow ( value . rgb , vec3 ( 0.41666 ) ) * 1.055 - vec3 ( 0.055 ) , value . rgb * 12.92 , vec3 ( lessThanEqual ( value . rgb , vec3 ( 0.0031308 ) ) ) ) , value . a ) ;
2026-01-28 17:19:36 +08:00
} ` ,R1= ` # ifdef USE _ENVMAP
2026-01-22 11:29:51 +08:00
# ifdef ENV _WORLDPOS
vec3 cameraToFrag ;
if ( isOrthographic ) {
cameraToFrag = normalize ( vec3 ( - viewMatrix [ 0 ] [ 2 ] , - viewMatrix [ 1 ] [ 2 ] , - viewMatrix [ 2 ] [ 2 ] ) ) ;
} else {
cameraToFrag = normalize ( vWorldPosition - cameraPosition ) ;
}
vec3 worldNormal = inverseTransformDirection ( normal , viewMatrix ) ;
# ifdef ENVMAP _MODE _REFLECTION
vec3 reflectVec = reflect ( cameraToFrag , worldNormal ) ;
# else
vec3 reflectVec = refract ( cameraToFrag , worldNormal , refractionRatio ) ;
# endif
# else
vec3 reflectVec = vReflect ;
# endif
# ifdef ENVMAP _TYPE _CUBE
vec4 envColor = textureCube ( envMap , envMapRotation * vec3 ( flipEnvMap * reflectVec . x , reflectVec . yz ) ) ;
# else
vec4 envColor = vec4 ( 0.0 ) ;
# endif
# ifdef ENVMAP _BLENDING _MULTIPLY
outgoingLight = mix ( outgoingLight , outgoingLight * envColor . xyz , specularStrength * reflectivity ) ;
# elif defined ( ENVMAP _BLENDING _MIX )
outgoingLight = mix ( outgoingLight , envColor . xyz , specularStrength * reflectivity ) ;
# elif defined ( ENVMAP _BLENDING _ADD )
outgoingLight += envColor . xyz * specularStrength * reflectivity ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,L1= ` # ifdef USE _ENVMAP
2026-01-22 11:29:51 +08:00
uniform float envMapIntensity ;
uniform float flipEnvMap ;
uniform mat3 envMapRotation ;
# ifdef ENVMAP _TYPE _CUBE
uniform samplerCube envMap ;
# else
uniform sampler2D envMap ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,D1= ` # ifdef USE _ENVMAP
2026-01-22 11:29:51 +08:00
uniform float reflectivity ;
# if defined ( USE _BUMPMAP ) || defined ( USE _NORMALMAP ) || defined ( PHONG ) || defined ( LAMBERT )
# define ENV _WORLDPOS
# endif
# ifdef ENV _WORLDPOS
varying vec3 vWorldPosition ;
uniform float refractionRatio ;
# else
varying vec3 vReflect ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,I1= ` # ifdef USE _ENVMAP
2026-01-22 11:29:51 +08:00
# if defined ( USE _BUMPMAP ) || defined ( USE _NORMALMAP ) || defined ( PHONG ) || defined ( LAMBERT )
# define ENV _WORLDPOS
# endif
# ifdef ENV _WORLDPOS
varying vec3 vWorldPosition ;
# else
varying vec3 vReflect ;
uniform float refractionRatio ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,B1= ` # ifdef USE _ENVMAP
2026-01-22 11:29:51 +08:00
# ifdef ENV _WORLDPOS
vWorldPosition = worldPosition . xyz ;
# else
vec3 cameraToVertex ;
if ( isOrthographic ) {
cameraToVertex = normalize ( vec3 ( - viewMatrix [ 0 ] [ 2 ] , - viewMatrix [ 1 ] [ 2 ] , - viewMatrix [ 2 ] [ 2 ] ) ) ;
} else {
cameraToVertex = normalize ( worldPosition . xyz - cameraPosition ) ;
}
vec3 worldNormal = inverseTransformDirection ( transformedNormal , viewMatrix ) ;
# ifdef ENVMAP _MODE _REFLECTION
vReflect = reflect ( cameraToVertex , worldNormal ) ;
# else
vReflect = refract ( cameraToVertex , worldNormal , refractionRatio ) ;
# endif
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,N1= ` # ifdef USE _FOG
2026-01-22 11:29:51 +08:00
vFogDepth = - mvPosition . z ;
2026-01-28 17:19:36 +08:00
# endif ` ,U1= ` # ifdef USE _FOG
2026-01-28 18:40:46 +08:00
varying float vFogDepth ;
# endif ` ,O1= ` # ifdef USE _FOG
2026-01-22 11:29:51 +08:00
# ifdef FOG _EXP2
float fogFactor = 1.0 - exp ( - fogDensity * fogDensity * vFogDepth * vFogDepth ) ;
# else
float fogFactor = smoothstep ( fogNear , fogFar , vFogDepth ) ;
# endif
gl _FragColor . rgb = mix ( gl _FragColor . rgb , fogColor , fogFactor ) ;
2026-01-28 18:40:46 +08:00
# endif ` ,k1= ` # ifdef USE _FOG
2026-01-22 11:29:51 +08:00
uniform vec3 fogColor ;
varying float vFogDepth ;
# ifdef FOG _EXP2
uniform float fogDensity ;
# else
uniform float fogNear ;
uniform float fogFar ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,F1= ` # ifdef USE _GRADIENTMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D gradientMap ;
# endif
vec3 getGradientIrradiance ( vec3 normal , vec3 lightDirection ) {
float dotNL = dot ( normal , lightDirection ) ;
vec2 coord = vec2 ( dotNL * 0.5 + 0.5 , 0.0 ) ;
# ifdef USE _GRADIENTMAP
return vec3 ( texture2D ( gradientMap , coord ) . r ) ;
# else
vec2 fw = fwidth ( coord ) * 0.5 ;
return mix ( vec3 ( 0.7 ) , vec3 ( 1.0 ) , smoothstep ( 0.7 - fw . x , 0.7 + fw . x , coord . x ) ) ;
# endif
2026-01-28 17:19:36 +08:00
} ` ,z1= ` # ifdef USE _LIGHTMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D lightMap ;
uniform float lightMapIntensity ;
2026-01-28 17:19:36 +08:00
# endif ` ,H1= ` LambertMaterial material ;
2026-01-22 11:29:51 +08:00
material . diffuseColor = diffuseColor . rgb ;
2026-01-28 17:19:36 +08:00
material . specularStrength = specularStrength ; ` ,V1= ` varying vec3 vViewPosition ;
2026-01-22 11:29:51 +08:00
struct LambertMaterial {
vec3 diffuseColor ;
float specularStrength ;
} ;
void RE _Direct _Lambert ( const in IncidentLight directLight , const in vec3 geometryPosition , const in vec3 geometryNormal , const in vec3 geometryViewDir , const in vec3 geometryClearcoatNormal , const in LambertMaterial material , inout ReflectedLight reflectedLight ) {
float dotNL = saturate ( dot ( geometryNormal , directLight . direction ) ) ;
vec3 irradiance = dotNL * directLight . color ;
reflectedLight . directDiffuse += irradiance * BRDF _Lambert ( material . diffuseColor ) ;
}
void RE _IndirectDiffuse _Lambert ( const in vec3 irradiance , const in vec3 geometryPosition , const in vec3 geometryNormal , const in vec3 geometryViewDir , const in vec3 geometryClearcoatNormal , const in LambertMaterial material , inout ReflectedLight reflectedLight ) {
reflectedLight . indirectDiffuse += irradiance * BRDF _Lambert ( material . diffuseColor ) ;
}
# define RE _Direct RE _Direct _Lambert
2026-01-28 17:19:36 +08:00
# define RE _IndirectDiffuse RE _IndirectDiffuse _Lambert ` ,G1= ` uniform bool receiveShadow ;
2026-01-22 11:29:51 +08:00
uniform vec3 ambientLightColor ;
# if defined ( USE _LIGHT _PROBES )
uniform vec3 lightProbe [ 9 ] ;
# endif
vec3 shGetIrradianceAt ( in vec3 normal , in vec3 shCoefficients [ 9 ] ) {
float x = normal . x , y = normal . y , z = normal . z ;
vec3 result = shCoefficients [ 0 ] * 0.886227 ;
result += shCoefficients [ 1 ] * 2.0 * 0.511664 * y ;
result += shCoefficients [ 2 ] * 2.0 * 0.511664 * z ;
result += shCoefficients [ 3 ] * 2.0 * 0.511664 * x ;
result += shCoefficients [ 4 ] * 2.0 * 0.429043 * x * y ;
result += shCoefficients [ 5 ] * 2.0 * 0.429043 * y * z ;
result += shCoefficients [ 6 ] * ( 0.743125 * z * z - 0.247708 ) ;
result += shCoefficients [ 7 ] * 2.0 * 0.429043 * x * z ;
result += shCoefficients [ 8 ] * 0.429043 * ( x * x - y * y ) ;
return result ;
}
vec3 getLightProbeIrradiance ( const in vec3 lightProbe [ 9 ] , const in vec3 normal ) {
vec3 worldNormal = inverseTransformDirection ( normal , viewMatrix ) ;
vec3 irradiance = shGetIrradianceAt ( worldNormal , lightProbe ) ;
return irradiance ;
}
vec3 getAmbientLightIrradiance ( const in vec3 ambientLightColor ) {
vec3 irradiance = ambientLightColor ;
return irradiance ;
}
float getDistanceAttenuation ( const in float lightDistance , const in float cutoffDistance , const in float decayExponent ) {
float distanceFalloff = 1.0 / max ( pow ( lightDistance , decayExponent ) , 0.01 ) ;
if ( cutoffDistance > 0.0 ) {
distanceFalloff *= pow2 ( saturate ( 1.0 - pow4 ( lightDistance / cutoffDistance ) ) ) ;
}
return distanceFalloff ;
}
float getSpotAttenuation ( const in float coneCosine , const in float penumbraCosine , const in float angleCosine ) {
return smoothstep ( coneCosine , penumbraCosine , angleCosine ) ;
}
# if NUM _DIR _LIGHTS > 0
struct DirectionalLight {
vec3 direction ;
vec3 color ;
} ;
uniform DirectionalLight directionalLights [ NUM _DIR _LIGHTS ] ;
void getDirectionalLightInfo ( const in DirectionalLight directionalLight , out IncidentLight light ) {
light . color = directionalLight . color ;
light . direction = directionalLight . direction ;
light . visible = true ;
}
# endif
# if NUM _POINT _LIGHTS > 0
struct PointLight {
vec3 position ;
vec3 color ;
float distance ;
float decay ;
} ;
uniform PointLight pointLights [ NUM _POINT _LIGHTS ] ;
void getPointLightInfo ( const in PointLight pointLight , const in vec3 geometryPosition , out IncidentLight light ) {
vec3 lVector = pointLight . position - geometryPosition ;
light . direction = normalize ( lVector ) ;
float lightDistance = length ( lVector ) ;
light . color = pointLight . color ;
light . color *= getDistanceAttenuation ( lightDistance , pointLight . distance , pointLight . decay ) ;
light . visible = ( light . color != vec3 ( 0.0 ) ) ;
}
# endif
# if NUM _SPOT _LIGHTS > 0
struct SpotLight {
vec3 position ;
vec3 direction ;
vec3 color ;
float distance ;
float decay ;
float coneCos ;
float penumbraCos ;
} ;
uniform SpotLight spotLights [ NUM _SPOT _LIGHTS ] ;
void getSpotLightInfo ( const in SpotLight spotLight , const in vec3 geometryPosition , out IncidentLight light ) {
vec3 lVector = spotLight . position - geometryPosition ;
light . direction = normalize ( lVector ) ;
float angleCos = dot ( light . direction , spotLight . direction ) ;
float spotAttenuation = getSpotAttenuation ( spotLight . coneCos , spotLight . penumbraCos , angleCos ) ;
if ( spotAttenuation > 0.0 ) {
float lightDistance = length ( lVector ) ;
light . color = spotLight . color * spotAttenuation ;
light . color *= getDistanceAttenuation ( lightDistance , spotLight . distance , spotLight . decay ) ;
light . visible = ( light . color != vec3 ( 0.0 ) ) ;
} else {
light . color = vec3 ( 0.0 ) ;
light . visible = false ;
}
}
# endif
# if NUM _RECT _AREA _LIGHTS > 0
struct RectAreaLight {
vec3 color ;
vec3 position ;
vec3 halfWidth ;
vec3 halfHeight ;
} ;
uniform sampler2D ltc _1 ; uniform sampler2D ltc _2 ;
uniform RectAreaLight rectAreaLights [ NUM _RECT _AREA _LIGHTS ] ;
# endif
# if NUM _HEMI _LIGHTS > 0
struct HemisphereLight {
vec3 direction ;
vec3 skyColor ;
vec3 groundColor ;
} ;
uniform HemisphereLight hemisphereLights [ NUM _HEMI _LIGHTS ] ;
vec3 getHemisphereLightIrradiance ( const in HemisphereLight hemiLight , const in vec3 normal ) {
float dotNL = dot ( normal , hemiLight . direction ) ;
float hemiDiffuseWeight = 0.5 * dotNL + 0.5 ;
vec3 irradiance = mix ( hemiLight . groundColor , hemiLight . skyColor , hemiDiffuseWeight ) ;
return irradiance ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,W1= ` # ifdef USE _ENVMAP
2026-01-22 11:29:51 +08:00
vec3 getIBLIrradiance ( const in vec3 normal ) {
# ifdef ENVMAP _TYPE _CUBE _UV
vec3 worldNormal = inverseTransformDirection ( normal , viewMatrix ) ;
vec4 envMapColor = textureCubeUV ( envMap , envMapRotation * worldNormal , 1.0 ) ;
return PI * envMapColor . rgb * envMapIntensity ;
# else
return vec3 ( 0.0 ) ;
# endif
}
vec3 getIBLRadiance ( const in vec3 viewDir , const in vec3 normal , const in float roughness ) {
# ifdef ENVMAP _TYPE _CUBE _UV
vec3 reflectVec = reflect ( - viewDir , normal ) ;
reflectVec = normalize ( mix ( reflectVec , normal , pow4 ( roughness ) ) ) ;
reflectVec = inverseTransformDirection ( reflectVec , viewMatrix ) ;
vec4 envMapColor = textureCubeUV ( envMap , envMapRotation * reflectVec , roughness ) ;
return envMapColor . rgb * envMapIntensity ;
# else
return vec3 ( 0.0 ) ;
# endif
}
# ifdef USE _ANISOTROPY
vec3 getIBLAnisotropyRadiance ( const in vec3 viewDir , const in vec3 normal , const in float roughness , const in vec3 bitangent , const in float anisotropy ) {
# ifdef ENVMAP _TYPE _CUBE _UV
vec3 bentNormal = cross ( bitangent , viewDir ) ;
bentNormal = normalize ( cross ( bentNormal , bitangent ) ) ;
bentNormal = normalize ( mix ( bentNormal , normal , pow2 ( pow2 ( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) ) ;
return getIBLRadiance ( viewDir , bentNormal , roughness ) ;
# else
return vec3 ( 0.0 ) ;
# endif
}
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,X1= ` ToonMaterial material ;
material . diffuseColor = diffuseColor . rgb ; ` ,j1= ` varying vec3 vViewPosition ;
2026-01-22 11:29:51 +08:00
struct ToonMaterial {
vec3 diffuseColor ;
} ;
void RE _Direct _Toon ( const in IncidentLight directLight , const in vec3 geometryPosition , const in vec3 geometryNormal , const in vec3 geometryViewDir , const in vec3 geometryClearcoatNormal , const in ToonMaterial material , inout ReflectedLight reflectedLight ) {
vec3 irradiance = getGradientIrradiance ( geometryNormal , directLight . direction ) * directLight . color ;
reflectedLight . directDiffuse += irradiance * BRDF _Lambert ( material . diffuseColor ) ;
}
void RE _IndirectDiffuse _Toon ( const in vec3 irradiance , const in vec3 geometryPosition , const in vec3 geometryNormal , const in vec3 geometryViewDir , const in vec3 geometryClearcoatNormal , const in ToonMaterial material , inout ReflectedLight reflectedLight ) {
reflectedLight . indirectDiffuse += irradiance * BRDF _Lambert ( material . diffuseColor ) ;
}
# define RE _Direct RE _Direct _Toon
2026-01-28 18:40:46 +08:00
# define RE _IndirectDiffuse RE _IndirectDiffuse _Toon ` ,Z1= ` BlinnPhongMaterial material ;
2026-01-22 11:29:51 +08:00
material . diffuseColor = diffuseColor . rgb ;
material . specularColor = specular ;
material . specularShininess = shininess ;
2026-01-28 18:40:46 +08:00
material . specularStrength = specularStrength ; ` ,q1= ` varying vec3 vViewPosition ;
2026-01-22 11:29:51 +08:00
struct BlinnPhongMaterial {
vec3 diffuseColor ;
vec3 specularColor ;
float specularShininess ;
float specularStrength ;
} ;
void RE _Direct _BlinnPhong ( const in IncidentLight directLight , const in vec3 geometryPosition , const in vec3 geometryNormal , const in vec3 geometryViewDir , const in vec3 geometryClearcoatNormal , const in BlinnPhongMaterial material , inout ReflectedLight reflectedLight ) {
float dotNL = saturate ( dot ( geometryNormal , directLight . direction ) ) ;
vec3 irradiance = dotNL * directLight . color ;
reflectedLight . directDiffuse += irradiance * BRDF _Lambert ( material . diffuseColor ) ;
reflectedLight . directSpecular += irradiance * BRDF _BlinnPhong ( directLight . direction , geometryViewDir , geometryNormal , material . specularColor , material . specularShininess ) * material . specularStrength ;
}
void RE _IndirectDiffuse _BlinnPhong ( const in vec3 irradiance , const in vec3 geometryPosition , const in vec3 geometryNormal , const in vec3 geometryViewDir , const in vec3 geometryClearcoatNormal , const in BlinnPhongMaterial material , inout ReflectedLight reflectedLight ) {
reflectedLight . indirectDiffuse += irradiance * BRDF _Lambert ( material . diffuseColor ) ;
}
# define RE _Direct RE _Direct _BlinnPhong
2026-01-28 17:19:36 +08:00
# define RE _IndirectDiffuse RE _IndirectDiffuse _BlinnPhong ` ,Y1= ` PhysicalMaterial material ;
2026-01-22 11:29:51 +08:00
material . diffuseColor = diffuseColor . rgb * ( 1.0 - metalnessFactor ) ;
vec3 dxy = max ( abs ( dFdx ( nonPerturbedNormal ) ) , abs ( dFdy ( nonPerturbedNormal ) ) ) ;
float geometryRoughness = max ( max ( dxy . x , dxy . y ) , dxy . z ) ;
material . roughness = max ( roughnessFactor , 0.0525 ) ; material . roughness += geometryRoughness ;
material . roughness = min ( material . roughness , 1.0 ) ;
# ifdef IOR
material . ior = ior ;
# ifdef USE _SPECULAR
float specularIntensityFactor = specularIntensity ;
vec3 specularColorFactor = specularColor ;
# ifdef USE _SPECULAR _COLORMAP
specularColorFactor *= texture2D ( specularColorMap , vSpecularColorMapUv ) . rgb ;
# endif
# ifdef USE _SPECULAR _INTENSITYMAP
specularIntensityFactor *= texture2D ( specularIntensityMap , vSpecularIntensityMapUv ) . a ;
# endif
material . specularF90 = mix ( specularIntensityFactor , 1.0 , metalnessFactor ) ;
# else
float specularIntensityFactor = 1.0 ;
vec3 specularColorFactor = vec3 ( 1.0 ) ;
material . specularF90 = 1.0 ;
# endif
material . specularColor = mix ( min ( pow2 ( ( material . ior - 1.0 ) / ( material . ior + 1.0 ) ) * specularColorFactor , vec3 ( 1.0 ) ) * specularIntensityFactor , diffuseColor . rgb , metalnessFactor ) ;
# else
material . specularColor = mix ( vec3 ( 0.04 ) , diffuseColor . rgb , metalnessFactor ) ;
material . specularF90 = 1.0 ;
# endif
# ifdef USE _CLEARCOAT
material . clearcoat = clearcoat ;
material . clearcoatRoughness = clearcoatRoughness ;
material . clearcoatF0 = vec3 ( 0.04 ) ;
material . clearcoatF90 = 1.0 ;
# ifdef USE _CLEARCOATMAP
material . clearcoat *= texture2D ( clearcoatMap , vClearcoatMapUv ) . x ;
# endif
# ifdef USE _CLEARCOAT _ROUGHNESSMAP
material . clearcoatRoughness *= texture2D ( clearcoatRoughnessMap , vClearcoatRoughnessMapUv ) . y ;
# endif
material . clearcoat = saturate ( material . clearcoat ) ; material . clearcoatRoughness = max ( material . clearcoatRoughness , 0.0525 ) ;
material . clearcoatRoughness += geometryRoughness ;
material . clearcoatRoughness = min ( material . clearcoatRoughness , 1.0 ) ;
# endif
# ifdef USE _DISPERSION
material . dispersion = dispersion ;
# endif
# ifdef USE _IRIDESCENCE
material . iridescence = iridescence ;
material . iridescenceIOR = iridescenceIOR ;
# ifdef USE _IRIDESCENCEMAP
material . iridescence *= texture2D ( iridescenceMap , vIridescenceMapUv ) . r ;
# endif
# ifdef USE _IRIDESCENCE _THICKNESSMAP
material . iridescenceThickness = ( iridescenceThicknessMaximum - iridescenceThicknessMinimum ) * texture2D ( iridescenceThicknessMap , vIridescenceThicknessMapUv ) . g + iridescenceThicknessMinimum ;
# else
material . iridescenceThickness = iridescenceThicknessMaximum ;
# endif
# endif
# ifdef USE _SHEEN
material . sheenColor = sheenColor ;
# ifdef USE _SHEEN _COLORMAP
material . sheenColor *= texture2D ( sheenColorMap , vSheenColorMapUv ) . rgb ;
# endif
material . sheenRoughness = clamp ( sheenRoughness , 0.07 , 1.0 ) ;
# ifdef USE _SHEEN _ROUGHNESSMAP
material . sheenRoughness *= texture2D ( sheenRoughnessMap , vSheenRoughnessMapUv ) . a ;
# endif
# endif
# ifdef USE _ANISOTROPY
# ifdef USE _ANISOTROPYMAP
mat2 anisotropyMat = mat2 ( anisotropyVector . x , anisotropyVector . y , - anisotropyVector . y , anisotropyVector . x ) ;
vec3 anisotropyPolar = texture2D ( anisotropyMap , vAnisotropyMapUv ) . rgb ;
vec2 anisotropyV = anisotropyMat * normalize ( 2.0 * anisotropyPolar . rg - vec2 ( 1.0 ) ) * anisotropyPolar . b ;
# else
vec2 anisotropyV = anisotropyVector ;
# endif
material . anisotropy = length ( anisotropyV ) ;
if ( material . anisotropy == 0.0 ) {
anisotropyV = vec2 ( 1.0 , 0.0 ) ;
} else {
anisotropyV /= material . anisotropy ;
material . anisotropy = saturate ( material . anisotropy ) ;
}
material . alphaT = mix ( pow2 ( material . roughness ) , 1.0 , pow2 ( material . anisotropy ) ) ;
material . anisotropyT = tbn [ 0 ] * anisotropyV . x + tbn [ 1 ] * anisotropyV . y ;
material . anisotropyB = tbn [ 1 ] * anisotropyV . x - tbn [ 0 ] * anisotropyV . y ;
2026-01-28 17:19:36 +08:00
# endif ` ,K1= ` uniform sampler2D dfgLUT ;
2026-01-22 11:29:51 +08:00
struct PhysicalMaterial {
vec3 diffuseColor ;
float roughness ;
vec3 specularColor ;
float specularF90 ;
float dispersion ;
# ifdef USE _CLEARCOAT
float clearcoat ;
float clearcoatRoughness ;
vec3 clearcoatF0 ;
float clearcoatF90 ;
# endif
# ifdef USE _IRIDESCENCE
float iridescence ;
float iridescenceIOR ;
float iridescenceThickness ;
vec3 iridescenceFresnel ;
vec3 iridescenceF0 ;
# endif
# ifdef USE _SHEEN
vec3 sheenColor ;
float sheenRoughness ;
# endif
# ifdef IOR
float ior ;
# endif
# ifdef USE _TRANSMISSION
float transmission ;
float transmissionAlpha ;
float thickness ;
float attenuationDistance ;
vec3 attenuationColor ;
# endif
# ifdef USE _ANISOTROPY
float anisotropy ;
float alphaT ;
vec3 anisotropyT ;
vec3 anisotropyB ;
# endif
} ;
vec3 clearcoatSpecularDirect = vec3 ( 0.0 ) ;
vec3 clearcoatSpecularIndirect = vec3 ( 0.0 ) ;
vec3 sheenSpecularDirect = vec3 ( 0.0 ) ;
vec3 sheenSpecularIndirect = vec3 ( 0.0 ) ;
vec3 Schlick _to _F0 ( const in vec3 f , const in float f90 , const in float dotVH ) {
float x = clamp ( 1.0 - dotVH , 0.0 , 1.0 ) ;
float x2 = x * x ;
float x5 = clamp ( x * x2 * x2 , 0.0 , 0.9999 ) ;
return ( f - vec3 ( f90 ) * x5 ) / ( 1.0 - x5 ) ;
}
float V _GGX _SmithCorrelated ( const in float alpha , const in float dotNL , const in float dotNV ) {
float a2 = pow2 ( alpha ) ;
float gv = dotNL * sqrt ( a2 + ( 1.0 - a2 ) * pow2 ( dotNV ) ) ;
float gl = dotNV * sqrt ( a2 + ( 1.0 - a2 ) * pow2 ( dotNL ) ) ;
return 0.5 / max ( gv + gl , EPSILON ) ;
}
float D _GGX ( const in float alpha , const in float dotNH ) {
float a2 = pow2 ( alpha ) ;
float denom = pow2 ( dotNH ) * ( a2 - 1.0 ) + 1.0 ;
return RECIPROCAL _PI * a2 / pow2 ( denom ) ;
}
# ifdef USE _ANISOTROPY
float V _GGX _SmithCorrelated _Anisotropic ( const in float alphaT , const in float alphaB , const in float dotTV , const in float dotBV , const in float dotTL , const in float dotBL , const in float dotNV , const in float dotNL ) {
float gv = dotNL * length ( vec3 ( alphaT * dotTV , alphaB * dotBV , dotNV ) ) ;
float gl = dotNV * length ( vec3 ( alphaT * dotTL , alphaB * dotBL , dotNL ) ) ;
float v = 0.5 / ( gv + gl ) ;
return saturate ( v ) ;
}
float D _GGX _Anisotropic ( const in float alphaT , const in float alphaB , const in float dotNH , const in float dotTH , const in float dotBH ) {
float a2 = alphaT * alphaB ;
highp vec3 v = vec3 ( alphaB * dotTH , alphaT * dotBH , a2 * dotNH ) ;
highp float v2 = dot ( v , v ) ;
float w2 = a2 / v2 ;
return RECIPROCAL _PI * a2 * pow2 ( w2 ) ;
}
# endif
# ifdef USE _CLEARCOAT
vec3 BRDF _GGX _Clearcoat ( const in vec3 lightDir , const in vec3 viewDir , const in vec3 normal , const in PhysicalMaterial material ) {
vec3 f0 = material . clearcoatF0 ;
float f90 = material . clearcoatF90 ;
float roughness = material . clearcoatRoughness ;
float alpha = pow2 ( roughness ) ;
vec3 halfDir = normalize ( lightDir + viewDir ) ;
float dotNL = saturate ( dot ( normal , lightDir ) ) ;
float dotNV = saturate ( dot ( normal , viewDir ) ) ;
float dotNH = saturate ( dot ( normal , halfDir ) ) ;
float dotVH = saturate ( dot ( viewDir , halfDir ) ) ;
vec3 F = F _Schlick ( f0 , f90 , dotVH ) ;
float V = V _GGX _SmithCorrelated ( alpha , dotNL , dotNV ) ;
float D = D _GGX ( alpha , dotNH ) ;
return F * ( V * D ) ;
}
# endif
vec3 BRDF _GGX ( const in vec3 lightDir , const in vec3 viewDir , const in vec3 normal , const in PhysicalMaterial material ) {
vec3 f0 = material . specularColor ;
float f90 = material . specularF90 ;
float roughness = material . roughness ;
float alpha = pow2 ( roughness ) ;
vec3 halfDir = normalize ( lightDir + viewDir ) ;
float dotNL = saturate ( dot ( normal , lightDir ) ) ;
float dotNV = saturate ( dot ( normal , viewDir ) ) ;
float dotNH = saturate ( dot ( normal , halfDir ) ) ;
float dotVH = saturate ( dot ( viewDir , halfDir ) ) ;
vec3 F = F _Schlick ( f0 , f90 , dotVH ) ;
# ifdef USE _IRIDESCENCE
F = mix ( F , material . iridescenceFresnel , material . iridescence ) ;
# endif
# ifdef USE _ANISOTROPY
float dotTL = dot ( material . anisotropyT , lightDir ) ;
float dotTV = dot ( material . anisotropyT , viewDir ) ;
float dotTH = dot ( material . anisotropyT , halfDir ) ;
float dotBL = dot ( material . anisotropyB , lightDir ) ;
float dotBV = dot ( material . anisotropyB , viewDir ) ;
float dotBH = dot ( material . anisotropyB , halfDir ) ;
float V = V _GGX _SmithCorrelated _Anisotropic ( material . alphaT , alpha , dotTV , dotBV , dotTL , dotBL , dotNV , dotNL ) ;
float D = D _GGX _Anisotropic ( material . alphaT , alpha , dotNH , dotTH , dotBH ) ;
# else
float V = V _GGX _SmithCorrelated ( alpha , dotNL , dotNV ) ;
float D = D _GGX ( alpha , dotNH ) ;
# endif
return F * ( V * D ) ;
}
vec2 LTC _Uv ( const in vec3 N , const in vec3 V , const in float roughness ) {
const float LUT _SIZE = 64.0 ;
const float LUT _SCALE = ( LUT _SIZE - 1.0 ) / LUT _SIZE ;
const float LUT _BIAS = 0.5 / LUT _SIZE ;
float dotNV = saturate ( dot ( N , V ) ) ;
vec2 uv = vec2 ( roughness , sqrt ( 1.0 - dotNV ) ) ;
uv = uv * LUT _SCALE + LUT _BIAS ;
return uv ;
}
float LTC _ClippedSphereFormFactor ( const in vec3 f ) {
float l = length ( f ) ;
return max ( ( l * l + f . z ) / ( l + 1.0 ) , 0.0 ) ;
}
vec3 LTC _EdgeVectorFormFactor ( const in vec3 v1 , const in vec3 v2 ) {
float x = dot ( v1 , v2 ) ;
float y = abs ( x ) ;
float a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y ;
float b = 3.4175940 + ( 4.1616724 + y ) * y ;
float v = a / b ;
float theta _sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt ( max ( 1.0 - x * x , 1e-7 ) ) - v ;
return cross ( v1 , v2 ) * theta _sintheta ;
}
vec3 LTC _Evaluate ( const in vec3 N , const in vec3 V , const in vec3 P , const in mat3 mInv , const in vec3 rectCoords [ 4 ] ) {
vec3 v1 = rectCoords [ 1 ] - rectCoords [ 0 ] ;
vec3 v2 = rectCoords [ 3 ] - rectCoords [ 0 ] ;
vec3 lightNormal = cross ( v1 , v2 ) ;
if ( dot ( lightNormal , P - rectCoords [ 0 ] ) < 0.0 ) return vec3 ( 0.0 ) ;
vec3 T1 , T2 ;
T1 = normalize ( V - N * dot ( V , N ) ) ;
T2 = - cross ( N , T1 ) ;
mat3 mat = mInv * transpose ( mat3 ( T1 , T2 , N ) ) ;
vec3 coords [ 4 ] ;
coords [ 0 ] = mat * ( rectCoords [ 0 ] - P ) ;
coords [ 1 ] = mat * ( rectCoords [ 1 ] - P ) ;
coords [ 2 ] = mat * ( rectCoords [ 2 ] - P ) ;
coords [ 3 ] = mat * ( rectCoords [ 3 ] - P ) ;
coords [ 0 ] = normalize ( coords [ 0 ] ) ;
coords [ 1 ] = normalize ( coords [ 1 ] ) ;
coords [ 2 ] = normalize ( coords [ 2 ] ) ;
coords [ 3 ] = normalize ( coords [ 3 ] ) ;
vec3 vectorFormFactor = vec3 ( 0.0 ) ;
vectorFormFactor += LTC _EdgeVectorFormFactor ( coords [ 0 ] , coords [ 1 ] ) ;
vectorFormFactor += LTC _EdgeVectorFormFactor ( coords [ 1 ] , coords [ 2 ] ) ;
vectorFormFactor += LTC _EdgeVectorFormFactor ( coords [ 2 ] , coords [ 3 ] ) ;
vectorFormFactor += LTC _EdgeVectorFormFactor ( coords [ 3 ] , coords [ 0 ] ) ;
float result = LTC _ClippedSphereFormFactor ( vectorFormFactor ) ;
return vec3 ( result ) ;
}
# if defined ( USE _SHEEN )
float D _Charlie ( float roughness , float dotNH ) {
float alpha = pow2 ( roughness ) ;
float invAlpha = 1.0 / alpha ;
float cos2h = dotNH * dotNH ;
float sin2h = max ( 1.0 - cos2h , 0.0078125 ) ;
return ( 2.0 + invAlpha ) * pow ( sin2h , invAlpha * 0.5 ) / ( 2.0 * PI ) ;
}
float V _Neubelt ( float dotNV , float dotNL ) {
return saturate ( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) ) ;
}
vec3 BRDF _Sheen ( const in vec3 lightDir , const in vec3 viewDir , const in vec3 normal , vec3 sheenColor , const in float sheenRoughness ) {
vec3 halfDir = normalize ( lightDir + viewDir ) ;
float dotNL = saturate ( dot ( normal , lightDir ) ) ;
float dotNV = saturate ( dot ( normal , viewDir ) ) ;
float dotNH = saturate ( dot ( normal , halfDir ) ) ;
float D = D _Charlie ( sheenRoughness , dotNH ) ;
float V = V _Neubelt ( dotNV , dotNL ) ;
return sheenColor * ( D * V ) ;
}
# endif
float IBLSheenBRDF ( const in vec3 normal , const in vec3 viewDir , const in float roughness ) {
float dotNV = saturate ( dot ( normal , viewDir ) ) ;
float r2 = roughness * roughness ;
float a = roughness < 0.25 ? - 339.2 * r2 + 161.4 * roughness - 25.9 : - 8.48 * r2 + 14.3 * roughness - 9.95 ;
float b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72 ;
float DG = exp ( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) ) ;
return saturate ( DG * RECIPROCAL _PI ) ;
}
vec2 DFGApprox ( const in vec3 normal , const in vec3 viewDir , const in float roughness ) {
float dotNV = saturate ( dot ( normal , viewDir ) ) ;
vec2 uv = vec2 ( roughness , dotNV ) ;
return texture2D ( dfgLUT , uv ) . rg ;
}
vec3 EnvironmentBRDF ( const in vec3 normal , const in vec3 viewDir , const in vec3 specularColor , const in float specularF90 , const in float roughness ) {
vec2 fab = DFGApprox ( normal , viewDir , roughness ) ;
return specularColor * fab . x + specularF90 * fab . y ;
}
# ifdef USE _IRIDESCENCE
void computeMultiscatteringIridescence ( const in vec3 normal , const in vec3 viewDir , const in vec3 specularColor , const in float specularF90 , const in float iridescence , const in vec3 iridescenceF0 , const in float roughness , inout vec3 singleScatter , inout vec3 multiScatter ) {
# else
void computeMultiscattering ( const in vec3 normal , const in vec3 viewDir , const in vec3 specularColor , const in float specularF90 , const in float roughness , inout vec3 singleScatter , inout vec3 multiScatter ) {
# endif
vec2 fab = DFGApprox ( normal , viewDir , roughness ) ;
# ifdef USE _IRIDESCENCE
vec3 Fr = mix ( specularColor , iridescenceF0 , iridescence ) ;
# else
vec3 Fr = specularColor ;
# endif
vec3 FssEss = Fr * fab . x + specularF90 * fab . y ;
float Ess = fab . x + fab . y ;
float Ems = 1.0 - Ess ;
vec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619 ; vec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg ) ;
singleScatter += FssEss ;
multiScatter += Fms * Ems ;
}
vec3 BRDF _GGX _Multiscatter ( const in vec3 lightDir , const in vec3 viewDir , const in vec3 normal , const in PhysicalMaterial material ) {
vec3 singleScatter = BRDF _GGX ( lightDir , viewDir , normal , material ) ;
float dotNL = saturate ( dot ( normal , lightDir ) ) ;
float dotNV = saturate ( dot ( normal , viewDir ) ) ;
vec2 dfgV = DFGApprox ( vec3 ( 0.0 , 0.0 , 1.0 ) , vec3 ( sqrt ( 1.0 - dotNV * dotNV ) , 0.0 , dotNV ) , material . roughness ) ;
vec2 dfgL = DFGApprox ( vec3 ( 0.0 , 0.0 , 1.0 ) , vec3 ( sqrt ( 1.0 - dotNL * dotNL ) , 0.0 , dotNL ) , material . roughness ) ;
vec3 FssEss _V = material . specularColor * dfgV . x + material . specularF90 * dfgV . y ;
vec3 FssEss _L = material . specularColor * dfgL . x + material . specularF90 * dfgL . y ;
float Ess _V = dfgV . x + dfgV . y ;
float Ess _L = dfgL . x + dfgL . y ;
float Ems _V = 1.0 - Ess _V ;
float Ems _L = 1.0 - Ess _L ;
vec3 Favg = material . specularColor + ( 1.0 - material . specularColor ) * 0.047619 ;
vec3 Fms = FssEss _V * FssEss _L * Favg / ( 1.0 - Ems _V * Ems _L * Favg * Favg + EPSILON ) ;
float compensationFactor = Ems _V * Ems _L ;
vec3 multiScatter = Fms * compensationFactor ;
return singleScatter + multiScatter ;
}
# if NUM _RECT _AREA _LIGHTS > 0
void RE _Direct _RectArea _Physical ( const in RectAreaLight rectAreaLight , const in vec3 geometryPosition , const in vec3 geometryNormal , const in vec3 geometryViewDir , const in vec3 geometryClearcoatNormal , const in PhysicalMaterial material , inout ReflectedLight reflectedLight ) {
vec3 normal = geometryNormal ;
vec3 viewDir = geometryViewDir ;
vec3 position = geometryPosition ;
vec3 lightPos = rectAreaLight . position ;
vec3 halfWidth = rectAreaLight . halfWidth ;
vec3 halfHeight = rectAreaLight . halfHeight ;
vec3 lightColor = rectAreaLight . color ;
float roughness = material . roughness ;
vec3 rectCoords [ 4 ] ;
rectCoords [ 0 ] = lightPos + halfWidth - halfHeight ; rectCoords [ 1 ] = lightPos - halfWidth - halfHeight ;
rectCoords [ 2 ] = lightPos - halfWidth + halfHeight ;
rectCoords [ 3 ] = lightPos + halfWidth + halfHeight ;
vec2 uv = LTC _Uv ( normal , viewDir , roughness ) ;
vec4 t1 = texture2D ( ltc _1 , uv ) ;
vec4 t2 = texture2D ( ltc _2 , uv ) ;
mat3 mInv = mat3 (
vec3 ( t1 . x , 0 , t1 . y ) ,
vec3 ( 0 , 1 , 0 ) ,
vec3 ( t1 . z , 0 , t1 . w )
) ;
vec3 fresnel = ( material . specularColor * t2 . x + ( vec3 ( 1.0 ) - material . specularColor ) * t2 . y ) ;
reflectedLight . directSpecular += lightColor * fresnel * LTC _Evaluate ( normal , viewDir , position , mInv , rectCoords ) ;
reflectedLight . directDiffuse += lightColor * material . diffuseColor * LTC _Evaluate ( normal , viewDir , position , mat3 ( 1.0 ) , rectCoords ) ;
}
# endif
void RE _Direct _Physical ( const in IncidentLight directLight , const in vec3 geometryPosition , const in vec3 geometryNormal , const in vec3 geometryViewDir , const in vec3 geometryClearcoatNormal , const in PhysicalMaterial material , inout ReflectedLight reflectedLight ) {
float dotNL = saturate ( dot ( geometryNormal , directLight . direction ) ) ;
vec3 irradiance = dotNL * directLight . color ;
# ifdef USE _CLEARCOAT
float dotNLcc = saturate ( dot ( geometryClearcoatNormal , directLight . direction ) ) ;
vec3 ccIrradiance = dotNLcc * directLight . color ;
clearcoatSpecularDirect += ccIrradiance * BRDF _GGX _Clearcoat ( directLight . direction , geometryViewDir , geometryClearcoatNormal , material ) ;
# endif
# ifdef USE _SHEEN
sheenSpecularDirect += irradiance * BRDF _Sheen ( directLight . direction , geometryViewDir , geometryNormal , material . sheenColor , material . sheenRoughness ) ;
# endif
reflectedLight . directSpecular += irradiance * BRDF _GGX _Multiscatter ( directLight . direction , geometryViewDir , geometryNormal , material ) ;
reflectedLight . directDiffuse += irradiance * BRDF _Lambert ( material . diffuseColor ) ;
}
void RE _IndirectDiffuse _Physical ( const in vec3 irradiance , const in vec3 geometryPosition , const in vec3 geometryNormal , const in vec3 geometryViewDir , const in vec3 geometryClearcoatNormal , const in PhysicalMaterial material , inout ReflectedLight reflectedLight ) {
reflectedLight . indirectDiffuse += irradiance * BRDF _Lambert ( material . diffuseColor ) ;
}
void RE _IndirectSpecular _Physical ( const in vec3 radiance , const in vec3 irradiance , const in vec3 clearcoatRadiance , const in vec3 geometryPosition , const in vec3 geometryNormal , const in vec3 geometryViewDir , const in vec3 geometryClearcoatNormal , const in PhysicalMaterial material , inout ReflectedLight reflectedLight ) {
# ifdef USE _CLEARCOAT
clearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF ( geometryClearcoatNormal , geometryViewDir , material . clearcoatF0 , material . clearcoatF90 , material . clearcoatRoughness ) ;
# endif
# ifdef USE _SHEEN
sheenSpecularIndirect += irradiance * material . sheenColor * IBLSheenBRDF ( geometryNormal , geometryViewDir , material . sheenRoughness ) ;
# endif
vec3 singleScattering = vec3 ( 0.0 ) ;
vec3 multiScattering = vec3 ( 0.0 ) ;
vec3 cosineWeightedIrradiance = irradiance * RECIPROCAL _PI ;
# ifdef USE _IRIDESCENCE
computeMultiscatteringIridescence ( geometryNormal , geometryViewDir , material . specularColor , material . specularF90 , material . iridescence , material . iridescenceFresnel , material . roughness , singleScattering , multiScattering ) ;
# else
computeMultiscattering ( geometryNormal , geometryViewDir , material . specularColor , material . specularF90 , material . roughness , singleScattering , multiScattering ) ;
# endif
vec3 totalScattering = singleScattering + multiScattering ;
vec3 diffuse = material . diffuseColor * ( 1.0 - max ( max ( totalScattering . r , totalScattering . g ) , totalScattering . b ) ) ;
reflectedLight . indirectSpecular += radiance * singleScattering ;
reflectedLight . indirectSpecular += multiScattering * cosineWeightedIrradiance ;
reflectedLight . indirectDiffuse += diffuse * cosineWeightedIrradiance ;
}
# define RE _Direct RE _Direct _Physical
# define RE _Direct _RectArea RE _Direct _RectArea _Physical
# define RE _IndirectDiffuse RE _IndirectDiffuse _Physical
# define RE _IndirectSpecular RE _IndirectSpecular _Physical
float computeSpecularOcclusion ( const in float dotNV , const in float ambientOcclusion , const in float roughness ) {
return saturate ( pow ( dotNV + ambientOcclusion , exp2 ( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion ) ;
2026-01-28 17:19:36 +08:00
} ` , $ 1= `
2026-01-22 11:29:51 +08:00
vec3 geometryPosition = - vViewPosition ;
vec3 geometryNormal = normal ;
vec3 geometryViewDir = ( isOrthographic ) ? vec3 ( 0 , 0 , 1 ) : normalize ( vViewPosition ) ;
vec3 geometryClearcoatNormal = vec3 ( 0.0 ) ;
# ifdef USE _CLEARCOAT
geometryClearcoatNormal = clearcoatNormal ;
# endif
# ifdef USE _IRIDESCENCE
float dotNVi = saturate ( dot ( normal , geometryViewDir ) ) ;
if ( material . iridescenceThickness == 0.0 ) {
material . iridescence = 0.0 ;
} else {
material . iridescence = saturate ( material . iridescence ) ;
}
if ( material . iridescence > 0.0 ) {
material . iridescenceFresnel = evalIridescence ( 1.0 , material . iridescenceIOR , dotNVi , material . iridescenceThickness , material . specularColor ) ;
material . iridescenceF0 = Schlick _to _F0 ( material . iridescenceFresnel , 1.0 , dotNVi ) ;
}
# endif
IncidentLight directLight ;
# if ( NUM _POINT _LIGHTS > 0 ) && defined ( RE _Direct )
PointLight pointLight ;
# if defined ( USE _SHADOWMAP ) && NUM _POINT _LIGHT _SHADOWS > 0
PointLightShadow pointLightShadow ;
# endif
# pragma unroll _loop _start
for ( int i = 0 ; i < NUM _POINT _LIGHTS ; i ++ ) {
pointLight = pointLights [ i ] ;
getPointLightInfo ( pointLight , geometryPosition , directLight ) ;
# if defined ( USE _SHADOWMAP ) && ( UNROLLED _LOOP _INDEX < NUM _POINT _LIGHT _SHADOWS )
pointLightShadow = pointLightShadows [ i ] ;
directLight . color *= ( directLight . visible && receiveShadow ) ? getPointShadow ( pointShadowMap [ i ] , pointLightShadow . shadowMapSize , pointLightShadow . shadowIntensity , pointLightShadow . shadowBias , pointLightShadow . shadowRadius , vPointShadowCoord [ i ] , pointLightShadow . shadowCameraNear , pointLightShadow . shadowCameraFar ) : 1.0 ;
# endif
RE _Direct ( directLight , geometryPosition , geometryNormal , geometryViewDir , geometryClearcoatNormal , material , reflectedLight ) ;
}
# pragma unroll _loop _end
# endif
# if ( NUM _SPOT _LIGHTS > 0 ) && defined ( RE _Direct )
SpotLight spotLight ;
vec4 spotColor ;
vec3 spotLightCoord ;
bool inSpotLightMap ;
# if defined ( USE _SHADOWMAP ) && NUM _SPOT _LIGHT _SHADOWS > 0
SpotLightShadow spotLightShadow ;
# endif
# pragma unroll _loop _start
for ( int i = 0 ; i < NUM _SPOT _LIGHTS ; i ++ ) {
spotLight = spotLights [ i ] ;
getSpotLightInfo ( spotLight , geometryPosition , directLight ) ;
# if ( UNROLLED _LOOP _INDEX < NUM _SPOT _LIGHT _SHADOWS _WITH _MAPS )
# define SPOT _LIGHT _MAP _INDEX UNROLLED _LOOP _INDEX
# elif ( UNROLLED _LOOP _INDEX < NUM _SPOT _LIGHT _SHADOWS )
# define SPOT _LIGHT _MAP _INDEX NUM _SPOT _LIGHT _MAPS
# else
# define SPOT _LIGHT _MAP _INDEX ( UNROLLED _LOOP _INDEX - NUM _SPOT _LIGHT _SHADOWS + NUM _SPOT _LIGHT _SHADOWS _WITH _MAPS )
# endif
# if ( SPOT _LIGHT _MAP _INDEX < NUM _SPOT _LIGHT _MAPS )
spotLightCoord = vSpotLightCoord [ i ] . xyz / vSpotLightCoord [ i ] . w ;
inSpotLightMap = all ( lessThan ( abs ( spotLightCoord * 2. - 1. ) , vec3 ( 1.0 ) ) ) ;
spotColor = texture2D ( spotLightMap [ SPOT _LIGHT _MAP _INDEX ] , spotLightCoord . xy ) ;
directLight . color = inSpotLightMap ? directLight . color * spotColor . rgb : directLight . color ;
# endif
# undef SPOT _LIGHT _MAP _INDEX
# if defined ( USE _SHADOWMAP ) && ( UNROLLED _LOOP _INDEX < NUM _SPOT _LIGHT _SHADOWS )
spotLightShadow = spotLightShadows [ i ] ;
directLight . color *= ( directLight . visible && receiveShadow ) ? getShadow ( spotShadowMap [ i ] , spotLightShadow . shadowMapSize , spotLightShadow . shadowIntensity , spotLightShadow . shadowBias , spotLightShadow . shadowRadius , vSpotLightCoord [ i ] ) : 1.0 ;
# endif
RE _Direct ( directLight , geometryPosition , geometryNormal , geometryViewDir , geometryClearcoatNormal , material , reflectedLight ) ;
}
# pragma unroll _loop _end
# endif
# if ( NUM _DIR _LIGHTS > 0 ) && defined ( RE _Direct )
DirectionalLight directionalLight ;
# if defined ( USE _SHADOWMAP ) && NUM _DIR _LIGHT _SHADOWS > 0
DirectionalLightShadow directionalLightShadow ;
# endif
# pragma unroll _loop _start
for ( int i = 0 ; i < NUM _DIR _LIGHTS ; i ++ ) {
directionalLight = directionalLights [ i ] ;
getDirectionalLightInfo ( directionalLight , directLight ) ;
# if defined ( USE _SHADOWMAP ) && ( UNROLLED _LOOP _INDEX < NUM _DIR _LIGHT _SHADOWS )
directionalLightShadow = directionalLightShadows [ i ] ;
directLight . color *= ( directLight . visible && receiveShadow ) ? getShadow ( directionalShadowMap [ i ] , directionalLightShadow . shadowMapSize , directionalLightShadow . shadowIntensity , directionalLightShadow . shadowBias , directionalLightShadow . shadowRadius , vDirectionalShadowCoord [ i ] ) : 1.0 ;
# endif
RE _Direct ( directLight , geometryPosition , geometryNormal , geometryViewDir , geometryClearcoatNormal , material , reflectedLight ) ;
}
# pragma unroll _loop _end
# endif
# if ( NUM _RECT _AREA _LIGHTS > 0 ) && defined ( RE _Direct _RectArea )
RectAreaLight rectAreaLight ;
# pragma unroll _loop _start
for ( int i = 0 ; i < NUM _RECT _AREA _LIGHTS ; i ++ ) {
rectAreaLight = rectAreaLights [ i ] ;
RE _Direct _RectArea ( rectAreaLight , geometryPosition , geometryNormal , geometryViewDir , geometryClearcoatNormal , material , reflectedLight ) ;
}
# pragma unroll _loop _end
# endif
# if defined ( RE _IndirectDiffuse )
vec3 iblIrradiance = vec3 ( 0.0 ) ;
vec3 irradiance = getAmbientLightIrradiance ( ambientLightColor ) ;
# if defined ( USE _LIGHT _PROBES )
irradiance += getLightProbeIrradiance ( lightProbe , geometryNormal ) ;
# endif
# if ( NUM _HEMI _LIGHTS > 0 )
# pragma unroll _loop _start
for ( int i = 0 ; i < NUM _HEMI _LIGHTS ; i ++ ) {
irradiance += getHemisphereLightIrradiance ( hemisphereLights [ i ] , geometryNormal ) ;
}
# pragma unroll _loop _end
# endif
# endif
# if defined ( RE _IndirectSpecular )
vec3 radiance = vec3 ( 0.0 ) ;
vec3 clearcoatRadiance = vec3 ( 0.0 ) ;
2026-01-28 17:19:36 +08:00
# endif ` ,J1= ` # if defined ( RE _IndirectDiffuse )
2026-01-22 11:29:51 +08:00
# ifdef USE _LIGHTMAP
vec4 lightMapTexel = texture2D ( lightMap , vLightMapUv ) ;
vec3 lightMapIrradiance = lightMapTexel . rgb * lightMapIntensity ;
irradiance += lightMapIrradiance ;
# endif
# if defined ( USE _ENVMAP ) && defined ( STANDARD ) && defined ( ENVMAP _TYPE _CUBE _UV )
iblIrradiance += getIBLIrradiance ( geometryNormal ) ;
# endif
# endif
# if defined ( USE _ENVMAP ) && defined ( RE _IndirectSpecular )
# ifdef USE _ANISOTROPY
radiance += getIBLAnisotropyRadiance ( geometryViewDir , geometryNormal , material . roughness , material . anisotropyB , material . anisotropy ) ;
# else
radiance += getIBLRadiance ( geometryViewDir , geometryNormal , material . roughness ) ;
# endif
# ifdef USE _CLEARCOAT
clearcoatRadiance += getIBLRadiance ( geometryViewDir , geometryClearcoatNormal , material . clearcoatRoughness ) ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,Q1= ` # if defined ( RE _IndirectDiffuse )
2026-01-22 11:29:51 +08:00
RE _IndirectDiffuse ( irradiance , geometryPosition , geometryNormal , geometryViewDir , geometryClearcoatNormal , material , reflectedLight ) ;
# endif
# if defined ( RE _IndirectSpecular )
RE _IndirectSpecular ( radiance , iblIrradiance , clearcoatRadiance , geometryPosition , geometryNormal , geometryViewDir , geometryClearcoatNormal , material , reflectedLight ) ;
2026-01-28 17:19:36 +08:00
# endif ` ,eb= ` # if defined ( USE _LOGARITHMIC _DEPTH _BUFFER )
2026-01-22 11:29:51 +08:00
gl _FragDepth = vIsPerspective == 0.0 ? gl _FragCoord . z : log2 ( vFragDepth ) * logDepthBufFC * 0.5 ;
2026-01-28 17:19:36 +08:00
# endif ` ,tb= ` # if defined ( USE _LOGARITHMIC _DEPTH _BUFFER )
2026-01-22 11:29:51 +08:00
uniform float logDepthBufFC ;
varying float vFragDepth ;
varying float vIsPerspective ;
2026-01-28 17:19:36 +08:00
# endif ` ,nb= ` # ifdef USE _LOGARITHMIC _DEPTH _BUFFER
2026-01-22 11:29:51 +08:00
varying float vFragDepth ;
varying float vIsPerspective ;
2026-01-28 17:19:36 +08:00
# endif ` ,ib= ` # ifdef USE _LOGARITHMIC _DEPTH _BUFFER
2026-01-22 11:29:51 +08:00
vFragDepth = 1.0 + gl _Position . w ;
vIsPerspective = float ( isPerspectiveMatrix ( projectionMatrix ) ) ;
2026-01-28 17:19:36 +08:00
# endif ` ,sb= ` # ifdef USE _MAP
2026-01-22 11:29:51 +08:00
vec4 sampledDiffuseColor = texture2D ( map , vMapUv ) ;
# ifdef DECODE _VIDEO _TEXTURE
sampledDiffuseColor = sRGBTransferEOTF ( sampledDiffuseColor ) ;
# endif
diffuseColor *= sampledDiffuseColor ;
2026-01-28 17:19:36 +08:00
# endif ` ,rb= ` # ifdef USE _MAP
2026-01-22 11:29:51 +08:00
uniform sampler2D map ;
2026-01-28 17:19:36 +08:00
# endif ` ,ob= ` # if defined ( USE _MAP ) || defined ( USE _ALPHAMAP )
2026-01-22 11:29:51 +08:00
# if defined ( USE _POINTS _UV )
vec2 uv = vUv ;
# else
vec2 uv = ( uvTransform * vec3 ( gl _PointCoord . x , 1.0 - gl _PointCoord . y , 1 ) ) . xy ;
# endif
# endif
# ifdef USE _MAP
diffuseColor *= texture2D ( map , uv ) ;
# endif
# ifdef USE _ALPHAMAP
diffuseColor . a *= texture2D ( alphaMap , uv ) . g ;
2026-01-28 17:19:36 +08:00
# endif ` ,ab= ` # if defined ( USE _POINTS _UV )
2026-01-22 11:29:51 +08:00
varying vec2 vUv ;
# else
# if defined ( USE _MAP ) || defined ( USE _ALPHAMAP )
uniform mat3 uvTransform ;
# endif
# endif
# ifdef USE _MAP
uniform sampler2D map ;
# endif
# ifdef USE _ALPHAMAP
uniform sampler2D alphaMap ;
2026-01-28 17:19:36 +08:00
# endif ` ,lb= ` float metalnessFactor = metalness ;
2026-01-22 11:29:51 +08:00
# ifdef USE _METALNESSMAP
vec4 texelMetalness = texture2D ( metalnessMap , vMetalnessMapUv ) ;
metalnessFactor *= texelMetalness . b ;
2026-01-28 17:19:36 +08:00
# endif ` ,cb= ` # ifdef USE _METALNESSMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D metalnessMap ;
2026-01-28 17:19:36 +08:00
# endif ` ,hb= ` # ifdef USE _INSTANCING _MORPH
2026-01-22 11:29:51 +08:00
float morphTargetInfluences [ MORPHTARGETS _COUNT ] ;
float morphTargetBaseInfluence = texelFetch ( morphTexture , ivec2 ( 0 , gl _InstanceID ) , 0 ) . r ;
for ( int i = 0 ; i < MORPHTARGETS _COUNT ; i ++ ) {
morphTargetInfluences [ i ] = texelFetch ( morphTexture , ivec2 ( i + 1 , gl _InstanceID ) , 0 ) . r ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,ub= ` # if defined ( USE _MORPHCOLORS )
2026-01-22 11:29:51 +08:00
vColor *= morphTargetBaseInfluence ;
for ( int i = 0 ; i < MORPHTARGETS _COUNT ; i ++ ) {
# if defined ( USE _COLOR _ALPHA )
if ( morphTargetInfluences [ i ] != 0.0 ) vColor += getMorph ( gl _VertexID , i , 2 ) * morphTargetInfluences [ i ] ;
# elif defined ( USE _COLOR )
if ( morphTargetInfluences [ i ] != 0.0 ) vColor += getMorph ( gl _VertexID , i , 2 ) . rgb * morphTargetInfluences [ i ] ;
# endif
}
2026-01-28 17:19:36 +08:00
# endif ` ,db= ` # ifdef USE _MORPHNORMALS
2026-01-22 11:29:51 +08:00
objectNormal *= morphTargetBaseInfluence ;
for ( int i = 0 ; i < MORPHTARGETS _COUNT ; i ++ ) {
if ( morphTargetInfluences [ i ] != 0.0 ) objectNormal += getMorph ( gl _VertexID , i , 1 ) . xyz * morphTargetInfluences [ i ] ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,fb= ` # ifdef USE _MORPHTARGETS
2026-01-22 11:29:51 +08:00
# ifndef USE _INSTANCING _MORPH
uniform float morphTargetBaseInfluence ;
uniform float morphTargetInfluences [ MORPHTARGETS _COUNT ] ;
# endif
uniform sampler2DArray morphTargetsTexture ;
uniform ivec2 morphTargetsTextureSize ;
vec4 getMorph ( const in int vertexIndex , const in int morphTargetIndex , const in int offset ) {
int texelIndex = vertexIndex * MORPHTARGETS _TEXTURE _STRIDE + offset ;
int y = texelIndex / morphTargetsTextureSize . x ;
int x = texelIndex - y * morphTargetsTextureSize . x ;
ivec3 morphUV = ivec3 ( x , y , morphTargetIndex ) ;
return texelFetch ( morphTargetsTexture , morphUV , 0 ) ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,pb= ` # ifdef USE _MORPHTARGETS
2026-01-22 11:29:51 +08:00
transformed *= morphTargetBaseInfluence ;
for ( int i = 0 ; i < MORPHTARGETS _COUNT ; i ++ ) {
if ( morphTargetInfluences [ i ] != 0.0 ) transformed += getMorph ( gl _VertexID , i , 0 ) . xyz * morphTargetInfluences [ i ] ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,mb= ` float faceDirection = gl _FrontFacing ? 1.0 : - 1.0 ;
2026-01-22 11:29:51 +08:00
# ifdef FLAT _SHADED
vec3 fdx = dFdx ( vViewPosition ) ;
vec3 fdy = dFdy ( vViewPosition ) ;
vec3 normal = normalize ( cross ( fdx , fdy ) ) ;
# else
vec3 normal = normalize ( vNormal ) ;
# ifdef DOUBLE _SIDED
normal *= faceDirection ;
# endif
# endif
# if defined ( USE _NORMALMAP _TANGENTSPACE ) || defined ( USE _CLEARCOAT _NORMALMAP ) || defined ( USE _ANISOTROPY )
# ifdef USE _TANGENT
mat3 tbn = mat3 ( normalize ( vTangent ) , normalize ( vBitangent ) , normal ) ;
# else
mat3 tbn = getTangentFrame ( - vViewPosition , normal ,
# if defined ( USE _NORMALMAP )
vNormalMapUv
# elif defined ( USE _CLEARCOAT _NORMALMAP )
vClearcoatNormalMapUv
# else
vUv
# endif
) ;
# endif
# if defined ( DOUBLE _SIDED ) && ! defined ( FLAT _SHADED )
tbn [ 0 ] *= faceDirection ;
tbn [ 1 ] *= faceDirection ;
# endif
# endif
# ifdef USE _CLEARCOAT _NORMALMAP
# ifdef USE _TANGENT
mat3 tbn2 = mat3 ( normalize ( vTangent ) , normalize ( vBitangent ) , normal ) ;
# else
mat3 tbn2 = getTangentFrame ( - vViewPosition , normal , vClearcoatNormalMapUv ) ;
# endif
# if defined ( DOUBLE _SIDED ) && ! defined ( FLAT _SHADED )
tbn2 [ 0 ] *= faceDirection ;
tbn2 [ 1 ] *= faceDirection ;
# endif
# endif
2026-01-28 17:19:36 +08:00
vec3 nonPerturbedNormal = normal ; ` ,gb= ` # ifdef USE _NORMALMAP _OBJECTSPACE
2026-01-22 11:29:51 +08:00
normal = texture2D ( normalMap , vNormalMapUv ) . xyz * 2.0 - 1.0 ;
# ifdef FLIP _SIDED
normal = - normal ;
# endif
# ifdef DOUBLE _SIDED
normal = normal * faceDirection ;
# endif
normal = normalize ( normalMatrix * normal ) ;
# elif defined ( USE _NORMALMAP _TANGENTSPACE )
vec3 mapN = texture2D ( normalMap , vNormalMapUv ) . xyz * 2.0 - 1.0 ;
mapN . xy *= normalScale ;
normal = normalize ( tbn * mapN ) ;
# elif defined ( USE _BUMPMAP )
normal = perturbNormalArb ( - vViewPosition , normal , dHdxy _fwd ( ) , faceDirection ) ;
2026-01-28 17:19:36 +08:00
# endif ` ,xb= ` # ifndef FLAT _SHADED
2026-01-22 11:29:51 +08:00
varying vec3 vNormal ;
# ifdef USE _TANGENT
varying vec3 vTangent ;
varying vec3 vBitangent ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,vb= ` # ifndef FLAT _SHADED
2026-01-22 11:29:51 +08:00
varying vec3 vNormal ;
# ifdef USE _TANGENT
varying vec3 vTangent ;
varying vec3 vBitangent ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,bb= ` # ifndef FLAT _SHADED
2026-01-22 11:29:51 +08:00
vNormal = normalize ( transformedNormal ) ;
# ifdef USE _TANGENT
vTangent = normalize ( transformedTangent ) ;
vBitangent = normalize ( cross ( vNormal , vTangent ) * tangent . w ) ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,yb= ` # ifdef USE _NORMALMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D normalMap ;
uniform vec2 normalScale ;
# endif
# ifdef USE _NORMALMAP _OBJECTSPACE
uniform mat3 normalMatrix ;
# endif
# if ! defined ( USE _TANGENT ) && ( defined ( USE _NORMALMAP _TANGENTSPACE ) || defined ( USE _CLEARCOAT _NORMALMAP ) || defined ( USE _ANISOTROPY ) )
mat3 getTangentFrame ( vec3 eye _pos , vec3 surf _norm , vec2 uv ) {
vec3 q0 = dFdx ( eye _pos . xyz ) ;
vec3 q1 = dFdy ( eye _pos . xyz ) ;
vec2 st0 = dFdx ( uv . st ) ;
vec2 st1 = dFdy ( uv . st ) ;
vec3 N = surf _norm ;
vec3 q1perp = cross ( q1 , N ) ;
vec3 q0perp = cross ( N , q0 ) ;
vec3 T = q1perp * st0 . x + q0perp * st1 . x ;
vec3 B = q1perp * st0 . y + q0perp * st1 . y ;
float det = max ( dot ( T , T ) , dot ( B , B ) ) ;
float scale = ( det == 0.0 ) ? 0.0 : inversesqrt ( det ) ;
return mat3 ( T * scale , B * scale , N ) ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,_b= ` # ifdef USE _CLEARCOAT
2026-01-22 11:29:51 +08:00
vec3 clearcoatNormal = nonPerturbedNormal ;
2026-01-28 17:19:36 +08:00
# endif ` ,Mb= ` # ifdef USE _CLEARCOAT _NORMALMAP
2026-01-22 11:29:51 +08:00
vec3 clearcoatMapN = texture2D ( clearcoatNormalMap , vClearcoatNormalMapUv ) . xyz * 2.0 - 1.0 ;
clearcoatMapN . xy *= clearcoatNormalScale ;
clearcoatNormal = normalize ( tbn2 * clearcoatMapN ) ;
2026-01-28 17:19:36 +08:00
# endif ` ,wb= ` # ifdef USE _CLEARCOATMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D clearcoatMap ;
# endif
# ifdef USE _CLEARCOAT _NORMALMAP
uniform sampler2D clearcoatNormalMap ;
uniform vec2 clearcoatNormalScale ;
# endif
# ifdef USE _CLEARCOAT _ROUGHNESSMAP
uniform sampler2D clearcoatRoughnessMap ;
2026-01-28 17:19:36 +08:00
# endif ` ,Sb= ` # ifdef USE _IRIDESCENCEMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D iridescenceMap ;
# endif
# ifdef USE _IRIDESCENCE _THICKNESSMAP
uniform sampler2D iridescenceThicknessMap ;
2026-01-28 17:19:36 +08:00
# endif ` ,Eb= ` # ifdef OPAQUE
2026-01-22 11:29:51 +08:00
diffuseColor . a = 1.0 ;
# endif
# ifdef USE _TRANSMISSION
diffuseColor . a *= material . transmissionAlpha ;
# endif
2026-01-28 17:19:36 +08:00
gl _FragColor = vec4 ( outgoingLight , diffuseColor . a ) ; ` ,Tb= ` vec3 packNormalToRGB ( const in vec3 normal ) {
2026-01-22 11:29:51 +08:00
return normalize ( normal ) * 0.5 + 0.5 ;
}
vec3 unpackRGBToNormal ( const in vec3 rgb ) {
return 2.0 * rgb . xyz - 1.0 ;
}
const float PackUpscale = 256. / 255. ; const float UnpackDownscale = 255. / 256. ; const float ShiftRight8 = 1. / 256. ;
const float Inv255 = 1. / 255. ;
const vec4 PackFactors = vec4 ( 1.0 , 256.0 , 256.0 * 256.0 , 256.0 * 256.0 * 256.0 ) ;
const vec2 UnpackFactors2 = vec2 ( UnpackDownscale , 1.0 / PackFactors . g ) ;
const vec3 UnpackFactors3 = vec3 ( UnpackDownscale / PackFactors . rg , 1.0 / PackFactors . b ) ;
const vec4 UnpackFactors4 = vec4 ( UnpackDownscale / PackFactors . rgb , 1.0 / PackFactors . a ) ;
vec4 packDepthToRGBA ( const in float v ) {
if ( v <= 0.0 )
return vec4 ( 0. , 0. , 0. , 0. ) ;
if ( v >= 1.0 )
return vec4 ( 1. , 1. , 1. , 1. ) ;
float vuf ;
float af = modf ( v * PackFactors . a , vuf ) ;
float bf = modf ( vuf * ShiftRight8 , vuf ) ;
float gf = modf ( vuf * ShiftRight8 , vuf ) ;
return vec4 ( vuf * Inv255 , gf * PackUpscale , bf * PackUpscale , af ) ;
}
vec3 packDepthToRGB ( const in float v ) {
if ( v <= 0.0 )
return vec3 ( 0. , 0. , 0. ) ;
if ( v >= 1.0 )
return vec3 ( 1. , 1. , 1. ) ;
float vuf ;
float bf = modf ( v * PackFactors . b , vuf ) ;
float gf = modf ( vuf * ShiftRight8 , vuf ) ;
return vec3 ( vuf * Inv255 , gf * PackUpscale , bf ) ;
}
vec2 packDepthToRG ( const in float v ) {
if ( v <= 0.0 )
return vec2 ( 0. , 0. ) ;
if ( v >= 1.0 )
return vec2 ( 1. , 1. ) ;
float vuf ;
float gf = modf ( v * 256. , vuf ) ;
return vec2 ( vuf * Inv255 , gf ) ;
}
float unpackRGBAToDepth ( const in vec4 v ) {
return dot ( v , UnpackFactors4 ) ;
}
float unpackRGBToDepth ( const in vec3 v ) {
return dot ( v , UnpackFactors3 ) ;
}
float unpackRGToDepth ( const in vec2 v ) {
return v . r * UnpackFactors2 . r + v . g * UnpackFactors2 . g ;
}
vec4 pack2HalfToRGBA ( const in vec2 v ) {
vec4 r = vec4 ( v . x , fract ( v . x * 255.0 ) , v . y , fract ( v . y * 255.0 ) ) ;
return vec4 ( r . x - r . y / 255.0 , r . y , r . z - r . w / 255.0 , r . w ) ;
}
vec2 unpackRGBATo2Half ( const in vec4 v ) {
return vec2 ( v . x + ( v . y / 255.0 ) , v . z + ( v . w / 255.0 ) ) ;
}
float viewZToOrthographicDepth ( const in float viewZ , const in float near , const in float far ) {
return ( viewZ + near ) / ( near - far ) ;
}
float orthographicDepthToViewZ ( const in float depth , const in float near , const in float far ) {
return depth * ( near - far ) - near ;
}
float viewZToPerspectiveDepth ( const in float viewZ , const in float near , const in float far ) {
return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ ) ;
}
float perspectiveDepthToViewZ ( const in float depth , const in float near , const in float far ) {
return ( near * far ) / ( ( far - near ) * depth - far ) ;
2026-01-28 17:19:36 +08:00
} ` ,Ab= ` # ifdef PREMULTIPLIED _ALPHA
2026-01-22 11:29:51 +08:00
gl _FragColor . rgb *= gl _FragColor . a ;
2026-01-28 17:19:36 +08:00
# endif ` ,Cb= ` vec4 mvPosition = vec4 ( transformed , 1.0 ) ;
2026-01-22 11:29:51 +08:00
# ifdef USE _BATCHING
mvPosition = batchingMatrix * mvPosition ;
# endif
# ifdef USE _INSTANCING
mvPosition = instanceMatrix * mvPosition ;
# endif
mvPosition = modelViewMatrix * mvPosition ;
2026-01-28 17:19:36 +08:00
gl _Position = projectionMatrix * mvPosition ; ` ,Pb= ` # ifdef DITHERING
2026-01-22 11:29:51 +08:00
gl _FragColor . rgb = dithering ( gl _FragColor . rgb ) ;
2026-01-28 17:19:36 +08:00
# endif ` ,Rb= ` # ifdef DITHERING
2026-01-22 11:29:51 +08:00
vec3 dithering ( vec3 color ) {
float grid _position = rand ( gl _FragCoord . xy ) ;
vec3 dither _shift _RGB = vec3 ( 0.25 / 255.0 , - 0.25 / 255.0 , 0.25 / 255.0 ) ;
dither _shift _RGB = mix ( 2.0 * dither _shift _RGB , - 2.0 * dither _shift _RGB , grid _position ) ;
return color + dither _shift _RGB ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,Lb= ` float roughnessFactor = roughness ;
2026-01-22 11:29:51 +08:00
# ifdef USE _ROUGHNESSMAP
vec4 texelRoughness = texture2D ( roughnessMap , vRoughnessMapUv ) ;
roughnessFactor *= texelRoughness . g ;
2026-01-28 17:19:36 +08:00
# endif ` ,Db= ` # ifdef USE _ROUGHNESSMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D roughnessMap ;
2026-01-28 17:19:36 +08:00
# endif ` ,Ib= ` # if NUM _SPOT _LIGHT _COORDS > 0
2026-01-22 11:29:51 +08:00
varying vec4 vSpotLightCoord [ NUM _SPOT _LIGHT _COORDS ] ;
# endif
# if NUM _SPOT _LIGHT _MAPS > 0
uniform sampler2D spotLightMap [ NUM _SPOT _LIGHT _MAPS ] ;
# endif
# ifdef USE _SHADOWMAP
# if NUM _DIR _LIGHT _SHADOWS > 0
uniform sampler2D directionalShadowMap [ NUM _DIR _LIGHT _SHADOWS ] ;
varying vec4 vDirectionalShadowCoord [ NUM _DIR _LIGHT _SHADOWS ] ;
struct DirectionalLightShadow {
float shadowIntensity ;
float shadowBias ;
float shadowNormalBias ;
float shadowRadius ;
vec2 shadowMapSize ;
} ;
uniform DirectionalLightShadow directionalLightShadows [ NUM _DIR _LIGHT _SHADOWS ] ;
# endif
# if NUM _SPOT _LIGHT _SHADOWS > 0
uniform sampler2D spotShadowMap [ NUM _SPOT _LIGHT _SHADOWS ] ;
struct SpotLightShadow {
float shadowIntensity ;
float shadowBias ;
float shadowNormalBias ;
float shadowRadius ;
vec2 shadowMapSize ;
} ;
uniform SpotLightShadow spotLightShadows [ NUM _SPOT _LIGHT _SHADOWS ] ;
# endif
# if NUM _POINT _LIGHT _SHADOWS > 0
uniform sampler2D pointShadowMap [ NUM _POINT _LIGHT _SHADOWS ] ;
varying vec4 vPointShadowCoord [ NUM _POINT _LIGHT _SHADOWS ] ;
struct PointLightShadow {
float shadowIntensity ;
float shadowBias ;
float shadowNormalBias ;
float shadowRadius ;
vec2 shadowMapSize ;
float shadowCameraNear ;
float shadowCameraFar ;
} ;
uniform PointLightShadow pointLightShadows [ NUM _POINT _LIGHT _SHADOWS ] ;
# endif
float texture2DCompare ( sampler2D depths , vec2 uv , float compare ) {
float depth = unpackRGBAToDepth ( texture2D ( depths , uv ) ) ;
# ifdef USE _REVERSED _DEPTH _BUFFER
return step ( depth , compare ) ;
# else
return step ( compare , depth ) ;
# endif
}
vec2 texture2DDistribution ( sampler2D shadow , vec2 uv ) {
return unpackRGBATo2Half ( texture2D ( shadow , uv ) ) ;
}
float VSMShadow ( sampler2D shadow , vec2 uv , float compare ) {
float occlusion = 1.0 ;
vec2 distribution = texture2DDistribution ( shadow , uv ) ;
# ifdef USE _REVERSED _DEPTH _BUFFER
float hard _shadow = step ( distribution . x , compare ) ;
# else
float hard _shadow = step ( compare , distribution . x ) ;
# endif
if ( hard _shadow != 1.0 ) {
float distance = compare - distribution . x ;
float variance = max ( 0.00000 , distribution . y * distribution . y ) ;
float softness _probability = variance / ( variance + distance * distance ) ; softness _probability = clamp ( ( softness _probability - 0.3 ) / ( 0.95 - 0.3 ) , 0.0 , 1.0 ) ; occlusion = clamp ( max ( hard _shadow , softness _probability ) , 0.0 , 1.0 ) ;
}
return occlusion ;
}
float getShadow ( sampler2D shadowMap , vec2 shadowMapSize , float shadowIntensity , float shadowBias , float shadowRadius , vec4 shadowCoord ) {
float shadow = 1.0 ;
shadowCoord . xyz /= shadowCoord . w ;
shadowCoord . z += shadowBias ;
bool inFrustum = shadowCoord . x >= 0.0 && shadowCoord . x <= 1.0 && shadowCoord . y >= 0.0 && shadowCoord . y <= 1.0 ;
bool frustumTest = inFrustum && shadowCoord . z <= 1.0 ;
if ( frustumTest ) {
# if defined ( SHADOWMAP _TYPE _PCF )
vec2 texelSize = vec2 ( 1.0 ) / shadowMapSize ;
float dx0 = - texelSize . x * shadowRadius ;
float dy0 = - texelSize . y * shadowRadius ;
float dx1 = + texelSize . x * shadowRadius ;
float dy1 = + texelSize . y * shadowRadius ;
float dx2 = dx0 / 2.0 ;
float dy2 = dy0 / 2.0 ;
float dx3 = dx1 / 2.0 ;
float dy3 = dy1 / 2.0 ;
shadow = (
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( dx0 , dy0 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( 0.0 , dy0 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( dx1 , dy0 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( dx2 , dy2 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( 0.0 , dy2 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( dx3 , dy2 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( dx0 , 0.0 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( dx2 , 0.0 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( dx3 , 0.0 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( dx1 , 0.0 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( dx2 , dy3 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( 0.0 , dy3 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( dx3 , dy3 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( dx0 , dy1 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( 0.0 , dy1 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , shadowCoord . xy + vec2 ( dx1 , dy1 ) , shadowCoord . z )
) * ( 1.0 / 17.0 ) ;
# elif defined ( SHADOWMAP _TYPE _PCF _SOFT )
vec2 texelSize = vec2 ( 1.0 ) / shadowMapSize ;
float dx = texelSize . x ;
float dy = texelSize . y ;
vec2 uv = shadowCoord . xy ;
vec2 f = fract ( uv * shadowMapSize + 0.5 ) ;
uv -= f * texelSize ;
shadow = (
texture2DCompare ( shadowMap , uv , shadowCoord . z ) +
texture2DCompare ( shadowMap , uv + vec2 ( dx , 0.0 ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , uv + vec2 ( 0.0 , dy ) , shadowCoord . z ) +
texture2DCompare ( shadowMap , uv + texelSize , shadowCoord . z ) +
mix ( texture2DCompare ( shadowMap , uv + vec2 ( - dx , 0.0 ) , shadowCoord . z ) ,
texture2DCompare ( shadowMap , uv + vec2 ( 2.0 * dx , 0.0 ) , shadowCoord . z ) ,
f . x ) +
mix ( texture2DCompare ( shadowMap , uv + vec2 ( - dx , dy ) , shadowCoord . z ) ,
texture2DCompare ( shadowMap , uv + vec2 ( 2.0 * dx , dy ) , shadowCoord . z ) ,
f . x ) +
mix ( texture2DCompare ( shadowMap , uv + vec2 ( 0.0 , - dy ) , shadowCoord . z ) ,
texture2DCompare ( shadowMap , uv + vec2 ( 0.0 , 2.0 * dy ) , shadowCoord . z ) ,
f . y ) +
mix ( texture2DCompare ( shadowMap , uv + vec2 ( dx , - dy ) , shadowCoord . z ) ,
texture2DCompare ( shadowMap , uv + vec2 ( dx , 2.0 * dy ) , shadowCoord . z ) ,
f . y ) +
mix ( mix ( texture2DCompare ( shadowMap , uv + vec2 ( - dx , - dy ) , shadowCoord . z ) ,
texture2DCompare ( shadowMap , uv + vec2 ( 2.0 * dx , - dy ) , shadowCoord . z ) ,
f . x ) ,
mix ( texture2DCompare ( shadowMap , uv + vec2 ( - dx , 2.0 * dy ) , shadowCoord . z ) ,
texture2DCompare ( shadowMap , uv + vec2 ( 2.0 * dx , 2.0 * dy ) , shadowCoord . z ) ,
f . x ) ,
f . y )
) * ( 1.0 / 9.0 ) ;
# elif defined ( SHADOWMAP _TYPE _VSM )
shadow = VSMShadow ( shadowMap , shadowCoord . xy , shadowCoord . z ) ;
# else
shadow = texture2DCompare ( shadowMap , shadowCoord . xy , shadowCoord . z ) ;
# endif
}
return mix ( 1.0 , shadow , shadowIntensity ) ;
}
vec2 cubeToUV ( vec3 v , float texelSizeY ) {
vec3 absV = abs ( v ) ;
float scaleToCube = 1.0 / max ( absV . x , max ( absV . y , absV . z ) ) ;
absV *= scaleToCube ;
v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY ) ;
vec2 planar = v . xy ;
float almostATexel = 1.5 * texelSizeY ;
float almostOne = 1.0 - almostATexel ;
if ( absV . z >= almostOne ) {
if ( v . z > 0.0 )
planar . x = 4.0 - v . x ;
} else if ( absV . x >= almostOne ) {
float signX = sign ( v . x ) ;
planar . x = v . z * signX + 2.0 * signX ;
} else if ( absV . y >= almostOne ) {
float signY = sign ( v . y ) ;
planar . x = v . x + 2.0 * signY + 2.0 ;
planar . y = v . z * signY - 2.0 ;
}
return vec2 ( 0.125 , 0.25 ) * planar + vec2 ( 0.375 , 0.75 ) ;
}
float getPointShadow ( sampler2D shadowMap , vec2 shadowMapSize , float shadowIntensity , float shadowBias , float shadowRadius , vec4 shadowCoord , float shadowCameraNear , float shadowCameraFar ) {
float shadow = 1.0 ;
vec3 lightToPosition = shadowCoord . xyz ;
float lightToPositionLength = length ( lightToPosition ) ;
if ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {
float dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear ) ; dp += shadowBias ;
vec3 bd3D = normalize ( lightToPosition ) ;
vec2 texelSize = vec2 ( 1.0 ) / ( shadowMapSize * vec2 ( 4.0 , 2.0 ) ) ;
# if defined ( SHADOWMAP _TYPE _PCF ) || defined ( SHADOWMAP _TYPE _PCF _SOFT ) || defined ( SHADOWMAP _TYPE _VSM )
vec2 offset = vec2 ( - 1 , 1 ) * shadowRadius * texelSize . y ;
shadow = (
texture2DCompare ( shadowMap , cubeToUV ( bd3D + offset . xyy , texelSize . y ) , dp ) +
texture2DCompare ( shadowMap , cubeToUV ( bd3D + offset . yyy , texelSize . y ) , dp ) +
texture2DCompare ( shadowMap , cubeToUV ( bd3D + offset . xyx , texelSize . y ) , dp ) +
texture2DCompare ( shadowMap , cubeToUV ( bd3D + offset . yyx , texelSize . y ) , dp ) +
texture2DCompare ( shadowMap , cubeToUV ( bd3D , texelSize . y ) , dp ) +
texture2DCompare ( shadowMap , cubeToUV ( bd3D + offset . xxy , texelSize . y ) , dp ) +
texture2DCompare ( shadowMap , cubeToUV ( bd3D + offset . yxy , texelSize . y ) , dp ) +
texture2DCompare ( shadowMap , cubeToUV ( bd3D + offset . xxx , texelSize . y ) , dp ) +
texture2DCompare ( shadowMap , cubeToUV ( bd3D + offset . yxx , texelSize . y ) , dp )
) * ( 1.0 / 9.0 ) ;
# else
shadow = texture2DCompare ( shadowMap , cubeToUV ( bd3D , texelSize . y ) , dp ) ;
# endif
}
return mix ( 1.0 , shadow , shadowIntensity ) ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,Bb= ` # if NUM _SPOT _LIGHT _COORDS > 0
2026-01-22 11:29:51 +08:00
uniform mat4 spotLightMatrix [ NUM _SPOT _LIGHT _COORDS ] ;
varying vec4 vSpotLightCoord [ NUM _SPOT _LIGHT _COORDS ] ;
# endif
# ifdef USE _SHADOWMAP
# if NUM _DIR _LIGHT _SHADOWS > 0
uniform mat4 directionalShadowMatrix [ NUM _DIR _LIGHT _SHADOWS ] ;
varying vec4 vDirectionalShadowCoord [ NUM _DIR _LIGHT _SHADOWS ] ;
struct DirectionalLightShadow {
float shadowIntensity ;
float shadowBias ;
float shadowNormalBias ;
float shadowRadius ;
vec2 shadowMapSize ;
} ;
uniform DirectionalLightShadow directionalLightShadows [ NUM _DIR _LIGHT _SHADOWS ] ;
# endif
# if NUM _SPOT _LIGHT _SHADOWS > 0
struct SpotLightShadow {
float shadowIntensity ;
float shadowBias ;
float shadowNormalBias ;
float shadowRadius ;
vec2 shadowMapSize ;
} ;
uniform SpotLightShadow spotLightShadows [ NUM _SPOT _LIGHT _SHADOWS ] ;
# endif
# if NUM _POINT _LIGHT _SHADOWS > 0
uniform mat4 pointShadowMatrix [ NUM _POINT _LIGHT _SHADOWS ] ;
varying vec4 vPointShadowCoord [ NUM _POINT _LIGHT _SHADOWS ] ;
struct PointLightShadow {
float shadowIntensity ;
float shadowBias ;
float shadowNormalBias ;
float shadowRadius ;
vec2 shadowMapSize ;
float shadowCameraNear ;
float shadowCameraFar ;
} ;
uniform PointLightShadow pointLightShadows [ NUM _POINT _LIGHT _SHADOWS ] ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,Nb= ` # if ( defined ( USE _SHADOWMAP ) && ( NUM _DIR _LIGHT _SHADOWS > 0 || NUM _POINT _LIGHT _SHADOWS > 0 ) ) || ( NUM _SPOT _LIGHT _COORDS > 0 )
2026-01-22 11:29:51 +08:00
vec3 shadowWorldNormal = inverseTransformDirection ( transformedNormal , viewMatrix ) ;
vec4 shadowWorldPosition ;
# endif
# if defined ( USE _SHADOWMAP )
# if NUM _DIR _LIGHT _SHADOWS > 0
# pragma unroll _loop _start
for ( int i = 0 ; i < NUM _DIR _LIGHT _SHADOWS ; i ++ ) {
shadowWorldPosition = worldPosition + vec4 ( shadowWorldNormal * directionalLightShadows [ i ] . shadowNormalBias , 0 ) ;
vDirectionalShadowCoord [ i ] = directionalShadowMatrix [ i ] * shadowWorldPosition ;
}
# pragma unroll _loop _end
# endif
# if NUM _POINT _LIGHT _SHADOWS > 0
# pragma unroll _loop _start
for ( int i = 0 ; i < NUM _POINT _LIGHT _SHADOWS ; i ++ ) {
shadowWorldPosition = worldPosition + vec4 ( shadowWorldNormal * pointLightShadows [ i ] . shadowNormalBias , 0 ) ;
vPointShadowCoord [ i ] = pointShadowMatrix [ i ] * shadowWorldPosition ;
}
# pragma unroll _loop _end
# endif
# endif
# if NUM _SPOT _LIGHT _COORDS > 0
# pragma unroll _loop _start
for ( int i = 0 ; i < NUM _SPOT _LIGHT _COORDS ; i ++ ) {
shadowWorldPosition = worldPosition ;
# if ( defined ( USE _SHADOWMAP ) && UNROLLED _LOOP _INDEX < NUM _SPOT _LIGHT _SHADOWS )
shadowWorldPosition . xyz += shadowWorldNormal * spotLightShadows [ i ] . shadowNormalBias ;
# endif
vSpotLightCoord [ i ] = spotLightMatrix [ i ] * shadowWorldPosition ;
}
# pragma unroll _loop _end
2026-01-28 18:40:46 +08:00
# endif ` ,Ub= ` float getShadowMask ( ) {
2026-01-22 11:29:51 +08:00
float shadow = 1.0 ;
# ifdef USE _SHADOWMAP
# if NUM _DIR _LIGHT _SHADOWS > 0
DirectionalLightShadow directionalLight ;
# pragma unroll _loop _start
for ( int i = 0 ; i < NUM _DIR _LIGHT _SHADOWS ; i ++ ) {
directionalLight = directionalLightShadows [ i ] ;
shadow *= receiveShadow ? getShadow ( directionalShadowMap [ i ] , directionalLight . shadowMapSize , directionalLight . shadowIntensity , directionalLight . shadowBias , directionalLight . shadowRadius , vDirectionalShadowCoord [ i ] ) : 1.0 ;
}
# pragma unroll _loop _end
# endif
# if NUM _SPOT _LIGHT _SHADOWS > 0
SpotLightShadow spotLight ;
# pragma unroll _loop _start
for ( int i = 0 ; i < NUM _SPOT _LIGHT _SHADOWS ; i ++ ) {
spotLight = spotLightShadows [ i ] ;
shadow *= receiveShadow ? getShadow ( spotShadowMap [ i ] , spotLight . shadowMapSize , spotLight . shadowIntensity , spotLight . shadowBias , spotLight . shadowRadius , vSpotLightCoord [ i ] ) : 1.0 ;
}
# pragma unroll _loop _end
# endif
# if NUM _POINT _LIGHT _SHADOWS > 0
PointLightShadow pointLight ;
# pragma unroll _loop _start
for ( int i = 0 ; i < NUM _POINT _LIGHT _SHADOWS ; i ++ ) {
pointLight = pointLightShadows [ i ] ;
shadow *= receiveShadow ? getPointShadow ( pointShadowMap [ i ] , pointLight . shadowMapSize , pointLight . shadowIntensity , pointLight . shadowBias , pointLight . shadowRadius , vPointShadowCoord [ i ] , pointLight . shadowCameraNear , pointLight . shadowCameraFar ) : 1.0 ;
}
# pragma unroll _loop _end
# endif
# endif
return shadow ;
2026-01-28 18:40:46 +08:00
} ` ,Ob= ` # ifdef USE _SKINNING
2026-01-22 11:29:51 +08:00
mat4 boneMatX = getBoneMatrix ( skinIndex . x ) ;
mat4 boneMatY = getBoneMatrix ( skinIndex . y ) ;
mat4 boneMatZ = getBoneMatrix ( skinIndex . z ) ;
mat4 boneMatW = getBoneMatrix ( skinIndex . w ) ;
2026-01-28 18:40:46 +08:00
# endif ` ,kb= ` # ifdef USE _SKINNING
2026-01-22 11:29:51 +08:00
uniform mat4 bindMatrix ;
uniform mat4 bindMatrixInverse ;
uniform highp sampler2D boneTexture ;
mat4 getBoneMatrix ( const in float i ) {
int size = textureSize ( boneTexture , 0 ) . x ;
int j = int ( i ) * 4 ;
int x = j % size ;
int y = j / size ;
vec4 v1 = texelFetch ( boneTexture , ivec2 ( x , y ) , 0 ) ;
vec4 v2 = texelFetch ( boneTexture , ivec2 ( x + 1 , y ) , 0 ) ;
vec4 v3 = texelFetch ( boneTexture , ivec2 ( x + 2 , y ) , 0 ) ;
vec4 v4 = texelFetch ( boneTexture , ivec2 ( x + 3 , y ) , 0 ) ;
return mat4 ( v1 , v2 , v3 , v4 ) ;
}
2026-01-28 17:19:36 +08:00
# endif ` ,Fb= ` # ifdef USE _SKINNING
2026-01-22 11:29:51 +08:00
vec4 skinVertex = bindMatrix * vec4 ( transformed , 1.0 ) ;
vec4 skinned = vec4 ( 0.0 ) ;
skinned += boneMatX * skinVertex * skinWeight . x ;
skinned += boneMatY * skinVertex * skinWeight . y ;
skinned += boneMatZ * skinVertex * skinWeight . z ;
skinned += boneMatW * skinVertex * skinWeight . w ;
transformed = ( bindMatrixInverse * skinned ) . xyz ;
2026-01-28 17:19:36 +08:00
# endif ` ,zb= ` # ifdef USE _SKINNING
2026-01-22 11:29:51 +08:00
mat4 skinMatrix = mat4 ( 0.0 ) ;
skinMatrix += skinWeight . x * boneMatX ;
skinMatrix += skinWeight . y * boneMatY ;
skinMatrix += skinWeight . z * boneMatZ ;
skinMatrix += skinWeight . w * boneMatW ;
skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix ;
objectNormal = vec4 ( skinMatrix * vec4 ( objectNormal , 0.0 ) ) . xyz ;
# ifdef USE _TANGENT
objectTangent = vec4 ( skinMatrix * vec4 ( objectTangent , 0.0 ) ) . xyz ;
# endif
2026-01-28 17:19:36 +08:00
# endif ` ,Hb= ` float specularStrength ;
2026-01-22 11:29:51 +08:00
# ifdef USE _SPECULARMAP
vec4 texelSpecular = texture2D ( specularMap , vSpecularMapUv ) ;
specularStrength = texelSpecular . r ;
# else
specularStrength = 1.0 ;
2026-01-28 17:19:36 +08:00
# endif ` ,Vb= ` # ifdef USE _SPECULARMAP
2026-01-22 11:29:51 +08:00
uniform sampler2D specularMap ;
2026-01-28 17:19:36 +08:00
# endif ` ,Gb= ` # if defined ( TONE _MAPPING )
2026-01-22 11:29:51 +08:00
gl _FragColor . rgb = toneMapping ( gl _FragColor . rgb ) ;
2026-01-28 17:19:36 +08:00
# endif ` ,Wb= ` # ifndef saturate
2026-01-22 11:29:51 +08:00
# define saturate ( a ) clamp ( a , 0.0 , 1.0 )
# endif
uniform float toneMappingExposure ;
vec3 LinearToneMapping ( vec3 color ) {
return saturate ( toneMappingExposure * color ) ;
}
vec3 ReinhardToneMapping ( vec3 color ) {
color *= toneMappingExposure ;
return saturate ( color / ( vec3 ( 1.0 ) + color ) ) ;
}
vec3 CineonToneMapping ( vec3 color ) {
color *= toneMappingExposure ;
color = max ( vec3 ( 0.0 ) , color - 0.004 ) ;
return pow ( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ) , vec3 ( 2.2 ) ) ;
}
vec3 RRTAndODTFit ( vec3 v ) {
vec3 a = v * ( v + 0.0245786 ) - 0.000090537 ;
vec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081 ;
return a / b ;
}
vec3 ACESFilmicToneMapping ( vec3 color ) {
const mat3 ACESInputMat = mat3 (
vec3 ( 0.59719 , 0.07600 , 0.02840 ) , vec3 ( 0.35458 , 0.90834 , 0.13383 ) ,
vec3 ( 0.04823 , 0.01566 , 0.83777 )
) ;
const mat3 ACESOutputMat = mat3 (
vec3 ( 1.60475 , - 0.10208 , - 0.00327 ) , vec3 ( - 0.53108 , 1.10813 , - 0.07276 ) ,
vec3 ( - 0.07367 , - 0.00605 , 1.07602 )
) ;
color *= toneMappingExposure / 0.6 ;
color = ACESInputMat * color ;
color = RRTAndODTFit ( color ) ;
color = ACESOutputMat * color ;
return saturate ( color ) ;
}
const mat3 LINEAR _REC2020 _TO _LINEAR _SRGB = mat3 (
vec3 ( 1.6605 , - 0.1246 , - 0.0182 ) ,
vec3 ( - 0.5876 , 1.1329 , - 0.1006 ) ,
vec3 ( - 0.0728 , - 0.0083 , 1.1187 )
) ;
const mat3 LINEAR _SRGB _TO _LINEAR _REC2020 = mat3 (
vec3 ( 0.6274 , 0.0691 , 0.0164 ) ,
vec3 ( 0.3293 , 0.9195 , 0.0880 ) ,
vec3 ( 0.0433 , 0.0113 , 0.8956 )
) ;
vec3 agxDefaultContrastApprox ( vec3 x ) {
vec3 x2 = x * x ;
vec3 x4 = x2 * x2 ;
return + 15.5 * x4 * x2
- 40.14 * x4 * x
+ 31.96 * x4
- 6.868 * x2 * x
+ 0.4298 * x2
+ 0.1191 * x
- 0.00232 ;
}
vec3 AgXToneMapping ( vec3 color ) {
const mat3 AgXInsetMatrix = mat3 (
vec3 ( 0.856627153315983 , 0.137318972929847 , 0.11189821299995 ) ,
vec3 ( 0.0951212405381588 , 0.761241990602591 , 0.0767994186031903 ) ,
vec3 ( 0.0482516061458583 , 0.101439036467562 , 0.811302368396859 )
) ;
const mat3 AgXOutsetMatrix = mat3 (
vec3 ( 1.1271005818144368 , - 0.1413297634984383 , - 0.14132976349843826 ) ,
vec3 ( - 0.11060664309660323 , 1.157823702216272 , - 0.11060664309660294 ) ,
vec3 ( - 0.016493938717834573 , - 0.016493938717834257 , 1.2519364065950405 )
) ;
const float AgxMinEv = - 12.47393 ; const float AgxMaxEv = 4.026069 ;
color *= toneMappingExposure ;
color = LINEAR _SRGB _TO _LINEAR _REC2020 * color ;
color = AgXInsetMatrix * color ;
color = max ( color , 1e-10 ) ; color = log2 ( color ) ;
color = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv ) ;
color = clamp ( color , 0.0 , 1.0 ) ;
color = agxDefaultContrastApprox ( color ) ;
color = AgXOutsetMatrix * color ;
color = pow ( max ( vec3 ( 0.0 ) , color ) , vec3 ( 2.2 ) ) ;
color = LINEAR _REC2020 _TO _LINEAR _SRGB * color ;
color = clamp ( color , 0.0 , 1.0 ) ;
return color ;
}
vec3 NeutralToneMapping ( vec3 color ) {
const float StartCompression = 0.8 - 0.04 ;
const float Desaturation = 0.15 ;
color *= toneMappingExposure ;
float x = min ( color . r , min ( color . g , color . b ) ) ;
float offset = x < 0.08 ? x - 6.25 * x * x : 0.04 ;
color -= offset ;
float peak = max ( color . r , max ( color . g , color . b ) ) ;
if ( peak < StartCompression ) return color ;
float d = 1. - StartCompression ;
float newPeak = 1. - d * d / ( peak + d - StartCompression ) ;
color *= newPeak / peak ;
float g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. ) ;
return mix ( color , vec3 ( newPeak ) , g ) ;
}
2026-01-28 17:19:36 +08:00
vec3 CustomToneMapping ( vec3 color ) { return color ; } ` ,Xb= ` # ifdef USE _TRANSMISSION
2026-01-22 11:29:51 +08:00
material . transmission = transmission ;
material . transmissionAlpha = 1.0 ;
material . thickness = thickness ;
material . attenuationDistance = attenuationDistance ;
material . attenuationColor = attenuationColor ;
# ifdef USE _TRANSMISSIONMAP
material . transmission *= texture2D ( transmissionMap , vTransmissionMapUv ) . r ;
# endif
# ifdef USE _THICKNESSMAP
material . thickness *= texture2D ( thicknessMap , vThicknessMapUv ) . g ;
# endif
vec3 pos = vWorldPosition ;
vec3 v = normalize ( cameraPosition - pos ) ;
vec3 n = inverseTransformDirection ( normal , viewMatrix ) ;
vec4 transmitted = getIBLVolumeRefraction (
n , v , material . roughness , material . diffuseColor , material . specularColor , material . specularF90 ,
pos , modelMatrix , viewMatrix , projectionMatrix , material . dispersion , material . ior , material . thickness ,
material . attenuationColor , material . attenuationDistance ) ;
material . transmissionAlpha = mix ( material . transmissionAlpha , transmitted . a , material . transmission ) ;
totalDiffuse = mix ( totalDiffuse , transmitted . rgb , material . transmission ) ;
2026-01-28 17:19:36 +08:00
# endif ` ,jb= ` # ifdef USE _TRANSMISSION
2026-01-22 11:29:51 +08:00
uniform float transmission ;
uniform float thickness ;
uniform float attenuationDistance ;
uniform vec3 attenuationColor ;
# ifdef USE _TRANSMISSIONMAP
uniform sampler2D transmissionMap ;
# endif
# ifdef USE _THICKNESSMAP
uniform sampler2D thicknessMap ;
# endif
uniform vec2 transmissionSamplerSize ;
uniform sampler2D transmissionSamplerMap ;
uniform mat4 modelMatrix ;
uniform mat4 projectionMatrix ;
varying vec3 vWorldPosition ;
float w0 ( float a ) {
return ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 ) ;
}
float w1 ( float a ) {
return ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 ) ;
}
float w2 ( float a ) {
return ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 ) ;
}
float w3 ( float a ) {
return ( 1.0 / 6.0 ) * ( a * a * a ) ;
}
float g0 ( float a ) {
return w0 ( a ) + w1 ( a ) ;
}
float g1 ( float a ) {
return w2 ( a ) + w3 ( a ) ;
}
float h0 ( float a ) {
return - 1.0 + w1 ( a ) / ( w0 ( a ) + w1 ( a ) ) ;
}
float h1 ( float a ) {
return 1.0 + w3 ( a ) / ( w2 ( a ) + w3 ( a ) ) ;
}
vec4 bicubic ( sampler2D tex , vec2 uv , vec4 texelSize , float lod ) {
uv = uv * texelSize . zw + 0.5 ;
vec2 iuv = floor ( uv ) ;
vec2 fuv = fract ( uv ) ;
float g0x = g0 ( fuv . x ) ;
float g1x = g1 ( fuv . x ) ;
float h0x = h0 ( fuv . x ) ;
float h1x = h1 ( fuv . x ) ;
float h0y = h0 ( fuv . y ) ;
float h1y = h1 ( fuv . y ) ;
vec2 p0 = ( vec2 ( iuv . x + h0x , iuv . y + h0y ) - 0.5 ) * texelSize . xy ;
vec2 p1 = ( vec2 ( iuv . x + h1x , iuv . y + h0y ) - 0.5 ) * texelSize . xy ;
vec2 p2 = ( vec2 ( iuv . x + h0x , iuv . y + h1y ) - 0.5 ) * texelSize . xy ;
vec2 p3 = ( vec2 ( iuv . x + h1x , iuv . y + h1y ) - 0.5 ) * texelSize . xy ;
return g0 ( fuv . y ) * ( g0x * textureLod ( tex , p0 , lod ) + g1x * textureLod ( tex , p1 , lod ) ) +
g1 ( fuv . y ) * ( g0x * textureLod ( tex , p2 , lod ) + g1x * textureLod ( tex , p3 , lod ) ) ;
}
vec4 textureBicubic ( sampler2D sampler , vec2 uv , float lod ) {
vec2 fLodSize = vec2 ( textureSize ( sampler , int ( lod ) ) ) ;
vec2 cLodSize = vec2 ( textureSize ( sampler , int ( lod + 1.0 ) ) ) ;
vec2 fLodSizeInv = 1.0 / fLodSize ;
vec2 cLodSizeInv = 1.0 / cLodSize ;
vec4 fSample = bicubic ( sampler , uv , vec4 ( fLodSizeInv , fLodSize ) , floor ( lod ) ) ;
vec4 cSample = bicubic ( sampler , uv , vec4 ( cLodSizeInv , cLodSize ) , ceil ( lod ) ) ;
return mix ( fSample , cSample , fract ( lod ) ) ;
}
vec3 getVolumeTransmissionRay ( const in vec3 n , const in vec3 v , const in float thickness , const in float ior , const in mat4 modelMatrix ) {
vec3 refractionVector = refract ( - v , normalize ( n ) , 1.0 / ior ) ;
vec3 modelScale ;
modelScale . x = length ( vec3 ( modelMatrix [ 0 ] . xyz ) ) ;
modelScale . y = length ( vec3 ( modelMatrix [ 1 ] . xyz ) ) ;
modelScale . z = length ( vec3 ( modelMatrix [ 2 ] . xyz ) ) ;
return normalize ( refractionVector ) * thickness * modelScale ;
}
float applyIorToRoughness ( const in float roughness , const in float ior ) {
return roughness * clamp ( ior * 2.0 - 2.0 , 0.0 , 1.0 ) ;
}
vec4 getTransmissionSample ( const in vec2 fragCoord , const in float roughness , const in float ior ) {
float lod = log2 ( transmissionSamplerSize . x ) * applyIorToRoughness ( roughness , ior ) ;
return textureBicubic ( transmissionSamplerMap , fragCoord . xy , lod ) ;
}
vec3 volumeAttenuation ( const in float transmissionDistance , const in vec3 attenuationColor , const in float attenuationDistance ) {
if ( isinf ( attenuationDistance ) ) {
return vec3 ( 1.0 ) ;
} else {
vec3 attenuationCoefficient = - log ( attenuationColor ) / attenuationDistance ;
vec3 transmittance = exp ( - attenuationCoefficient * transmissionDistance ) ; return transmittance ;
}
}
vec4 getIBLVolumeRefraction ( const in vec3 n , const in vec3 v , const in float roughness , const in vec3 diffuseColor ,
const in vec3 specularColor , const in float specularF90 , const in vec3 position , const in mat4 modelMatrix ,
const in mat4 viewMatrix , const in mat4 projMatrix , const in float dispersion , const in float ior , const in float thickness ,
const in vec3 attenuationColor , const in float attenuationDistance ) {
vec4 transmittedLight ;
vec3 transmittance ;
# ifdef USE _DISPERSION
float halfSpread = ( ior - 1.0 ) * 0.025 * dispersion ;
vec3 iors = vec3 ( ior - halfSpread , ior , ior + halfSpread ) ;
for ( int i = 0 ; i < 3 ; i ++ ) {
vec3 transmissionRay = getVolumeTransmissionRay ( n , v , thickness , iors [ i ] , modelMatrix ) ;
vec3 refractedRayExit = position + transmissionRay ;
vec4 ndcPos = projMatrix * viewMatrix * vec4 ( refractedRayExit , 1.0 ) ;
vec2 refractionCoords = ndcPos . xy / ndcPos . w ;
refractionCoords += 1.0 ;
refractionCoords /= 2.0 ;
vec4 transmissionSample = getTransmissionSample ( refractionCoords , roughness , iors [ i ] ) ;
transmittedLight [ i ] = transmissionSample [ i ] ;
transmittedLight . a += transmissionSample . a ;
transmittance [ i ] = diffuseColor [ i ] * volumeAttenuation ( length ( transmissionRay ) , attenuationColor , attenuationDistance ) [ i ] ;
}
transmittedLight . a /= 3.0 ;
# else
vec3 transmissionRay = getVolumeTransmissionRay ( n , v , thickness , ior , modelMatrix ) ;
vec3 refractedRayExit = position + transmissionRay ;
vec4 ndcPos = projMatrix * viewMatrix * vec4 ( refractedRayExit , 1.0 ) ;
vec2 refractionCoords = ndcPos . xy / ndcPos . w ;
refractionCoords += 1.0 ;
refractionCoords /= 2.0 ;
transmittedLight = getTransmissionSample ( refractionCoords , roughness , ior ) ;
transmittance = diffuseColor * volumeAttenuation ( length ( transmissionRay ) , attenuationColor , attenuationDistance ) ;
# endif
vec3 attenuatedColor = transmittance * transmittedLight . rgb ;
vec3 F = EnvironmentBRDF ( n , v , specularColor , specularF90 , roughness ) ;
float transmittanceFactor = ( transmittance . r + transmittance . g + transmittance . b ) / 3.0 ;
return vec4 ( ( 1.0 - F ) * attenuatedColor , 1.0 - ( 1.0 - transmittedLight . a ) * transmittanceFactor ) ;
}
2026-01-28 18:40:46 +08:00
# endif ` ,Zb= ` # if defined ( USE _UV ) || defined ( USE _ANISOTROPY )
2026-01-22 11:29:51 +08:00
varying vec2 vUv ;
# endif
# ifdef USE _MAP
varying vec2 vMapUv ;
# endif
# ifdef USE _ALPHAMAP
varying vec2 vAlphaMapUv ;
# endif
# ifdef USE _LIGHTMAP
varying vec2 vLightMapUv ;
# endif
# ifdef USE _AOMAP
varying vec2 vAoMapUv ;
# endif
# ifdef USE _BUMPMAP
varying vec2 vBumpMapUv ;
# endif
# ifdef USE _NORMALMAP
varying vec2 vNormalMapUv ;
# endif
# ifdef USE _EMISSIVEMAP
varying vec2 vEmissiveMapUv ;
# endif
# ifdef USE _METALNESSMAP
varying vec2 vMetalnessMapUv ;
# endif
# ifdef USE _ROUGHNESSMAP
varying vec2 vRoughnessMapUv ;
# endif
# ifdef USE _ANISOTROPYMAP
varying vec2 vAnisotropyMapUv ;
# endif
# ifdef USE _CLEARCOATMAP
varying vec2 vClearcoatMapUv ;
# endif
# ifdef USE _CLEARCOAT _NORMALMAP
varying vec2 vClearcoatNormalMapUv ;
# endif
# ifdef USE _CLEARCOAT _ROUGHNESSMAP
varying vec2 vClearcoatRoughnessMapUv ;
# endif
# ifdef USE _IRIDESCENCEMAP
varying vec2 vIridescenceMapUv ;
# endif
# ifdef USE _IRIDESCENCE _THICKNESSMAP
varying vec2 vIridescenceThicknessMapUv ;
# endif
# ifdef USE _SHEEN _COLORMAP
varying vec2 vSheenColorMapUv ;
# endif
# ifdef USE _SHEEN _ROUGHNESSMAP
varying vec2 vSheenRoughnessMapUv ;
# endif
# ifdef USE _SPECULARMAP
varying vec2 vSpecularMapUv ;
# endif
# ifdef USE _SPECULAR _COLORMAP
varying vec2 vSpecularColorMapUv ;
# endif
# ifdef USE _SPECULAR _INTENSITYMAP
varying vec2 vSpecularIntensityMapUv ;
# endif
# ifdef USE _TRANSMISSIONMAP
uniform mat3 transmissionMapTransform ;
varying vec2 vTransmissionMapUv ;
# endif
# ifdef USE _THICKNESSMAP
uniform mat3 thicknessMapTransform ;
varying vec2 vThicknessMapUv ;
2026-01-28 18:40:46 +08:00
# endif ` ,qb= ` # if defined ( USE _UV ) || defined ( USE _ANISOTROPY )
2026-01-22 11:29:51 +08:00
varying vec2 vUv ;
# endif
# ifdef USE _MAP
uniform mat3 mapTransform ;
varying vec2 vMapUv ;
# endif
# ifdef USE _ALPHAMAP
uniform mat3 alphaMapTransform ;
varying vec2 vAlphaMapUv ;
# endif
# ifdef USE _LIGHTMAP
uniform mat3 lightMapTransform ;
varying vec2 vLightMapUv ;
# endif
# ifdef USE _AOMAP
uniform mat3 aoMapTransform ;
varying vec2 vAoMapUv ;
# endif
# ifdef USE _BUMPMAP
uniform mat3 bumpMapTransform ;
varying vec2 vBumpMapUv ;
# endif
# ifdef USE _NORMALMAP
uniform mat3 normalMapTransform ;
varying vec2 vNormalMapUv ;
# endif
# ifdef USE _DISPLACEMENTMAP
uniform mat3 displacementMapTransform ;
varying vec2 vDisplacementMapUv ;
# endif
# ifdef USE _EMISSIVEMAP
uniform mat3 emissiveMapTransform ;
varying vec2 vEmissiveMapUv ;
# endif
# ifdef USE _METALNESSMAP
uniform mat3 metalnessMapTransform ;
varying vec2 vMetalnessMapUv ;
# endif
# ifdef USE _ROUGHNESSMAP
uniform mat3 roughnessMapTransform ;
varying vec2 vRoughnessMapUv ;
# endif
# ifdef USE _ANISOTROPYMAP
uniform mat3 anisotropyMapTransform ;
varying vec2 vAnisotropyMapUv ;
# endif
# ifdef USE _CLEARCOATMAP
uniform mat3 clearcoatMapTransform ;
varying vec2 vClearcoatMapUv ;
# endif
# ifdef USE _CLEARCOAT _NORMALMAP
uniform mat3 clearcoatNormalMapTransform ;
varying vec2 vClearcoatNormalMapUv ;
# endif
# ifdef USE _CLEARCOAT _ROUGHNESSMAP
uniform mat3 clearcoatRoughnessMapTransform ;
varying vec2 vClearcoatRoughnessMapUv ;
# endif
# ifdef USE _SHEEN _COLORMAP
uniform mat3 sheenColorMapTransform ;
varying vec2 vSheenColorMapUv ;
# endif
# ifdef USE _SHEEN _ROUGHNESSMAP
uniform mat3 sheenRoughnessMapTransform ;
varying vec2 vSheenRoughnessMapUv ;
# endif
# ifdef USE _IRIDESCENCEMAP
uniform mat3 iridescenceMapTransform ;
varying vec2 vIridescenceMapUv ;
# endif
# ifdef USE _IRIDESCENCE _THICKNESSMAP
uniform mat3 iridescenceThicknessMapTransform ;
varying vec2 vIridescenceThicknessMapUv ;
# endif
# ifdef USE _SPECULARMAP
uniform mat3 specularMapTransform ;
varying vec2 vSpecularMapUv ;
# endif
# ifdef USE _SPECULAR _COLORMAP
uniform mat3 specularColorMapTransform ;
varying vec2 vSpecularColorMapUv ;
# endif
# ifdef USE _SPECULAR _INTENSITYMAP
uniform mat3 specularIntensityMapTransform ;
varying vec2 vSpecularIntensityMapUv ;
# endif
# ifdef USE _TRANSMISSIONMAP
uniform mat3 transmissionMapTransform ;
varying vec2 vTransmissionMapUv ;
# endif
# ifdef USE _THICKNESSMAP
uniform mat3 thicknessMapTransform ;
varying vec2 vThicknessMapUv ;
2026-01-28 17:19:36 +08:00
# endif ` ,Yb= ` # if defined ( USE _UV ) || defined ( USE _ANISOTROPY )
2026-01-22 11:29:51 +08:00
vUv = vec3 ( uv , 1 ) . xy ;
# endif
# ifdef USE _MAP
vMapUv = ( mapTransform * vec3 ( MAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _ALPHAMAP
vAlphaMapUv = ( alphaMapTransform * vec3 ( ALPHAMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _LIGHTMAP
vLightMapUv = ( lightMapTransform * vec3 ( LIGHTMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _AOMAP
vAoMapUv = ( aoMapTransform * vec3 ( AOMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _BUMPMAP
vBumpMapUv = ( bumpMapTransform * vec3 ( BUMPMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _NORMALMAP
vNormalMapUv = ( normalMapTransform * vec3 ( NORMALMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _DISPLACEMENTMAP
vDisplacementMapUv = ( displacementMapTransform * vec3 ( DISPLACEMENTMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _EMISSIVEMAP
vEmissiveMapUv = ( emissiveMapTransform * vec3 ( EMISSIVEMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _METALNESSMAP
vMetalnessMapUv = ( metalnessMapTransform * vec3 ( METALNESSMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _ROUGHNESSMAP
vRoughnessMapUv = ( roughnessMapTransform * vec3 ( ROUGHNESSMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _ANISOTROPYMAP
vAnisotropyMapUv = ( anisotropyMapTransform * vec3 ( ANISOTROPYMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _CLEARCOATMAP
vClearcoatMapUv = ( clearcoatMapTransform * vec3 ( CLEARCOATMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _CLEARCOAT _NORMALMAP
vClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3 ( CLEARCOAT _NORMALMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _CLEARCOAT _ROUGHNESSMAP
vClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3 ( CLEARCOAT _ROUGHNESSMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _IRIDESCENCEMAP
vIridescenceMapUv = ( iridescenceMapTransform * vec3 ( IRIDESCENCEMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _IRIDESCENCE _THICKNESSMAP
vIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3 ( IRIDESCENCE _THICKNESSMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _SHEEN _COLORMAP
vSheenColorMapUv = ( sheenColorMapTransform * vec3 ( SHEEN _COLORMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _SHEEN _ROUGHNESSMAP
vSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3 ( SHEEN _ROUGHNESSMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _SPECULARMAP
vSpecularMapUv = ( specularMapTransform * vec3 ( SPECULARMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _SPECULAR _COLORMAP
vSpecularColorMapUv = ( specularColorMapTransform * vec3 ( SPECULAR _COLORMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _SPECULAR _INTENSITYMAP
vSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3 ( SPECULAR _INTENSITYMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _TRANSMISSIONMAP
vTransmissionMapUv = ( transmissionMapTransform * vec3 ( TRANSMISSIONMAP _UV , 1 ) ) . xy ;
# endif
# ifdef USE _THICKNESSMAP
vThicknessMapUv = ( thicknessMapTransform * vec3 ( THICKNESSMAP _UV , 1 ) ) . xy ;
2026-01-28 17:19:36 +08:00
# endif ` ,Kb= ` # if defined ( USE _ENVMAP ) || defined ( DISTANCE ) || defined ( USE _SHADOWMAP ) || defined ( USE _TRANSMISSION ) || NUM _SPOT _LIGHT _COORDS > 0
2026-01-22 11:29:51 +08:00
vec4 worldPosition = vec4 ( transformed , 1.0 ) ;
# ifdef USE _BATCHING
worldPosition = batchingMatrix * worldPosition ;
# endif
# ifdef USE _INSTANCING
worldPosition = instanceMatrix * worldPosition ;
# endif
worldPosition = modelMatrix * worldPosition ;
2026-01-28 18:40:46 +08:00
# endif ` ;const et={alphahash_fragment:Jv,alphahash_pars_fragment:Qv,alphamap_fragment:e1,alphamap_pars_fragment:t1,alphatest_fragment:n1,alphatest_pars_fragment:i1,aomap_fragment:s1,aomap_pars_fragment:r1,batching_pars_vertex:o1,batching_vertex:a1,begin_vertex:l1,beginnormal_vertex:c1,bsdfs:h1,iridescence_fragment:u1,bumpmap_pars_fragment:d1,clipping_planes_fragment:f1,clipping_planes_pars_fragment:p1,clipping_planes_pars_vertex:m1,clipping_planes_vertex:g1,color_fragment:x1,color_pars_fragment:v1,color_pars_vertex:b1,color_vertex:y1,common:_1,cube_uv_reflection_fragment:M1,defaultnormal_vertex:w1,displacementmap_pars_vertex:S1,displacementmap_vertex:E1,emissivemap_fragment:T1,emissivemap_pars_fragment:A1,colorspace_fragment:C1,colorspace_pars_fragment:P1,envmap_fragment:R1,envmap_common_pars_fragment:L1,envmap_pars_fragment:D1,envmap_pars_vertex:I1,envmap_physical_pars_fragment:W1,envmap_vertex:B1,fog_vertex:N1,fog_pars_vertex:U1,fog_fragment:O1,fog_pars_fragment:k1,gradientmap_pars_fragment:F1,lightmap_pars_fragment:z1,lights_lambert_fragment:H1,lights_lambert_pars_fragment:V1,lights_pars_begin:G1,lights_toon_fragment:X1,lights_toon_pars_fragment:j1,lights_phong_fragment:Z1,lights_phong_pars_fragment:q1,lights_physical_fragment:Y1,lights_physical_pars_fragment:K1,lights_fragment_begin: $ 1,lights_fragment_maps:J1,lights_fragment_end:Q1,logdepthbuf_fragment:eb,logdepthbuf_pars_fragment:tb,logdepthbuf_pars_vertex:nb,logdepthbuf_vertex:ib,map_fragment:sb,map_pars_fragment:rb,map_particle_fragment:ob,map_particle_pars_fragment:ab,metalnessmap_fragment:lb,metalnessmap_pars_fragment:cb,morphinstance_vertex:hb,morphcolor_vertex:ub,morphnormal_vertex:db,morphtarget_pars_vertex:fb,morphtarget_vertex:pb,normal_fragment_begin:mb,normal_fragment_maps:gb,normal_pars_fragment:xb,normal_pars_vertex:vb,normal_vertex:bb,normalmap_pars_fragment:yb,clearcoat_normal_fragment_begin:_b,clearcoat_normal_fragment_maps:Mb,clearcoat_pars_fragment:wb,iridescence_pars_fragment:Sb,opaque_fragment:Eb,packing:Tb,premultiplied_alpha_fragment:Ab,project_vertex:Cb,dithering_fragment:Pb,dithering_pars_fragment:Rb,roughnessmap_fragment:Lb,roughnessmap_pars_fragment:Db,shadowmap_pars_fragment:Ib,shadowmap_pars_vertex:Bb,shadowmap_vertex:Nb,shadowmask_pars_fragment:Ub,skinbase_vertex:Ob,skinning_pars_vertex:kb,skinning_vertex:Fb,skinnormal_vertex:zb,specularmap_fragment:Hb,specularmap_pars_fragment:Vb,tonemapping_fragment:Gb,tonemapping_pars_fragment:Wb,transmission_fragment:Xb,transmission_pars_fragment:jb,uv_pars_fragment:Zb,uv_pars_vertex:qb,uv_vertex:Yb,worldpos_vertex:Kb,background_vert: ` varying vec2 vUv ;
2026-01-22 11:29:51 +08:00
uniform mat3 uvTransform ;
void main ( ) {
vUv = ( uvTransform * vec3 ( uv , 1 ) ) . xy ;
gl _Position = vec4 ( position . xy , 1.0 , 1.0 ) ;
} ` ,background_frag: ` uniform sampler2D t2D ;
uniform float backgroundIntensity ;
varying vec2 vUv ;
void main ( ) {
vec4 texColor = texture2D ( t2D , vUv ) ;
# ifdef DECODE _VIDEO _TEXTURE
texColor = vec4 ( mix ( pow ( texColor . rgb * 0.9478672986 + vec3 ( 0.0521327014 ) , vec3 ( 2.4 ) ) , texColor . rgb * 0.0773993808 , vec3 ( lessThanEqual ( texColor . rgb , vec3 ( 0.04045 ) ) ) ) , texColor . w ) ;
# endif
texColor . rgb *= backgroundIntensity ;
gl _FragColor = texColor ;
# include < tonemapping _fragment >
# include < colorspace _fragment >
} ` ,backgroundCube_vert: ` varying vec3 vWorldDirection ;
# include < common >
void main ( ) {
vWorldDirection = transformDirection ( position , modelMatrix ) ;
# include < begin _vertex >
# include < project _vertex >
gl _Position . z = gl _Position . w ;
} ` ,backgroundCube_frag: ` # ifdef ENVMAP _TYPE _CUBE
uniform samplerCube envMap ;
# elif defined ( ENVMAP _TYPE _CUBE _UV )
uniform sampler2D envMap ;
# endif
uniform float flipEnvMap ;
uniform float backgroundBlurriness ;
uniform float backgroundIntensity ;
uniform mat3 backgroundRotation ;
varying vec3 vWorldDirection ;
# include < cube _uv _reflection _fragment >
void main ( ) {
# ifdef ENVMAP _TYPE _CUBE
vec4 texColor = textureCube ( envMap , backgroundRotation * vec3 ( flipEnvMap * vWorldDirection . x , vWorldDirection . yz ) ) ;
# elif defined ( ENVMAP _TYPE _CUBE _UV )
vec4 texColor = textureCubeUV ( envMap , backgroundRotation * vWorldDirection , backgroundBlurriness ) ;
# else
vec4 texColor = vec4 ( 0.0 , 0.0 , 0.0 , 1.0 ) ;
# endif
texColor . rgb *= backgroundIntensity ;
gl _FragColor = texColor ;
# include < tonemapping _fragment >
# include < colorspace _fragment >
} ` ,cube_vert: ` varying vec3 vWorldDirection ;
# include < common >
void main ( ) {
vWorldDirection = transformDirection ( position , modelMatrix ) ;
# include < begin _vertex >
# include < project _vertex >
gl _Position . z = gl _Position . w ;
} ` ,cube_frag: ` uniform samplerCube tCube ;
uniform float tFlip ;
uniform float opacity ;
varying vec3 vWorldDirection ;
void main ( ) {
vec4 texColor = textureCube ( tCube , vec3 ( tFlip * vWorldDirection . x , vWorldDirection . yz ) ) ;
gl _FragColor = texColor ;
gl _FragColor . a *= opacity ;
# include < tonemapping _fragment >
# include < colorspace _fragment >
} ` ,depth_vert: ` # include < common >
# include < batching _pars _vertex >
# include < uv _pars _vertex >
# include < displacementmap _pars _vertex >
# include < morphtarget _pars _vertex >
# include < skinning _pars _vertex >
# include < logdepthbuf _pars _vertex >
# include < clipping _planes _pars _vertex >
varying vec2 vHighPrecisionZW ;
void main ( ) {
# include < uv _vertex >
# include < batching _vertex >
# include < skinbase _vertex >
# include < morphinstance _vertex >
# ifdef USE _DISPLACEMENTMAP
# include < beginnormal _vertex >
# include < morphnormal _vertex >
# include < skinnormal _vertex >
# endif
# include < begin _vertex >
# include < morphtarget _vertex >
# include < skinning _vertex >
# include < displacementmap _vertex >
# include < project _vertex >
# include < logdepthbuf _vertex >
# include < clipping _planes _vertex >
vHighPrecisionZW = gl _Position . zw ;
} ` ,depth_frag: ` # if DEPTH _PACKING == 3200
uniform float opacity ;
# endif
# include < common >
# include < packing >
# include < uv _pars _fragment >
# include < map _pars _fragment >
# include < alphamap _pars _fragment >
# include < alphatest _pars _fragment >
# include < alphahash _pars _fragment >
# include < logdepthbuf _pars _fragment >
# include < clipping _planes _pars _fragment >
varying vec2 vHighPrecisionZW ;
void main ( ) {
vec4 diffuseColor = vec4 ( 1.0 ) ;
# include < clipping _planes _fragment >
# if DEPTH _PACKING == 3200
diffuseColor . a = opacity ;
# endif
# include < map _fragment >
# include < alphamap _fragment >
# include < alphatest _fragment >
# include < alphahash _fragment >
# include < logdepthbuf _fragment >
# ifdef USE _REVERSED _DEPTH _BUFFER
float fragCoordZ = vHighPrecisionZW [ 0 ] / vHighPrecisionZW [ 1 ] ;
# else
float fragCoordZ = 0.5 * vHighPrecisionZW [ 0 ] / vHighPrecisionZW [ 1 ] + 0.5 ;
# endif
# if DEPTH _PACKING == 3200
gl _FragColor = vec4 ( vec3 ( 1.0 - fragCoordZ ) , opacity ) ;
# elif DEPTH _PACKING == 3201
gl _FragColor = packDepthToRGBA ( fragCoordZ ) ;
# elif DEPTH _PACKING == 3202
gl _FragColor = vec4 ( packDepthToRGB ( fragCoordZ ) , 1.0 ) ;
# elif DEPTH _PACKING == 3203
gl _FragColor = vec4 ( packDepthToRG ( fragCoordZ ) , 0.0 , 1.0 ) ;
# endif
} ` ,distanceRGBA_vert: ` # define DISTANCE
varying vec3 vWorldPosition ;
# include < common >
# include < batching _pars _vertex >
# include < uv _pars _vertex >
# include < displacementmap _pars _vertex >
# include < morphtarget _pars _vertex >
# include < skinning _pars _vertex >
# include < clipping _planes _pars _vertex >
void main ( ) {
# include < uv _vertex >
# include < batching _vertex >
# include < skinbase _vertex >
# include < morphinstance _vertex >
# ifdef USE _DISPLACEMENTMAP
# include < beginnormal _vertex >
# include < morphnormal _vertex >
# include < skinnormal _vertex >
# endif
# include < begin _vertex >
# include < morphtarget _vertex >
# include < skinning _vertex >
# include < displacementmap _vertex >
# include < project _vertex >
# include < worldpos _vertex >
# include < clipping _planes _vertex >
vWorldPosition = worldPosition . xyz ;
} ` ,distanceRGBA_frag: ` # define DISTANCE
uniform vec3 referencePosition ;
uniform float nearDistance ;
uniform float farDistance ;
varying vec3 vWorldPosition ;
# include < common >
# include < packing >
# include < uv _pars _fragment >
# include < map _pars _fragment >
# include < alphamap _pars _fragment >
# include < alphatest _pars _fragment >
# include < alphahash _pars _fragment >
# include < clipping _planes _pars _fragment >
void main ( ) {
vec4 diffuseColor = vec4 ( 1.0 ) ;
# include < clipping _planes _fragment >
# include < map _fragment >
# include < alphamap _fragment >
# include < alphatest _fragment >
# include < alphahash _fragment >
float dist = length ( vWorldPosition - referencePosition ) ;
dist = ( dist - nearDistance ) / ( farDistance - nearDistance ) ;
dist = saturate ( dist ) ;
gl _FragColor = packDepthToRGBA ( dist ) ;
} ` ,equirect_vert: ` varying vec3 vWorldDirection ;
# include < common >
void main ( ) {
vWorldDirection = transformDirection ( position , modelMatrix ) ;
# include < begin _vertex >
# include < project _vertex >
} ` ,equirect_frag: ` uniform sampler2D tEquirect ;
varying vec3 vWorldDirection ;
# include < common >
void main ( ) {
vec3 direction = normalize ( vWorldDirection ) ;
vec2 sampleUV = equirectUv ( direction ) ;
gl _FragColor = texture2D ( tEquirect , sampleUV ) ;
# include < tonemapping _fragment >
# include < colorspace _fragment >
} ` ,linedashed_vert: ` uniform float scale ;
attribute float lineDistance ;
varying float vLineDistance ;
# include < common >
# include < uv _pars _vertex >
# include < color _pars _vertex >
# include < fog _pars _vertex >
# include < morphtarget _pars _vertex >
# include < logdepthbuf _pars _vertex >
# include < clipping _planes _pars _vertex >
void main ( ) {
vLineDistance = scale * lineDistance ;
# include < uv _vertex >
# include < color _vertex >
# include < morphinstance _vertex >
# include < morphcolor _vertex >
# include < begin _vertex >
# include < morphtarget _vertex >
# include < project _vertex >
# include < logdepthbuf _vertex >
# include < clipping _planes _vertex >
# include < fog _vertex >
} ` ,linedashed_frag: ` uniform vec3 diffuse ;
uniform float opacity ;
uniform float dashSize ;
uniform float totalSize ;
varying float vLineDistance ;
# include < common >
# include < color _pars _fragment >
# include < uv _pars _fragment >
# include < map _pars _fragment >
# include < fog _pars _fragment >
# include < logdepthbuf _pars _fragment >
# include < clipping _planes _pars _fragment >
void main ( ) {
vec4 diffuseColor = vec4 ( diffuse , opacity ) ;
# include < clipping _planes _fragment >
if ( mod ( vLineDistance , totalSize ) > dashSize ) {
discard ;
}
vec3 outgoingLight = vec3 ( 0.0 ) ;
# include < logdepthbuf _fragment >
# include < map _fragment >
# include < color _fragment >
outgoingLight = diffuseColor . rgb ;
# include < opaque _fragment >
# include < tonemapping _fragment >
# include < colorspace _fragment >
# include < fog _fragment >
# include < premultiplied _alpha _fragment >
} ` ,meshbasic_vert: ` # include < common >
# include < batching _pars _vertex >
# include < uv _pars _vertex >
# include < envmap _pars _vertex >
# include < color _pars _vertex >
# include < fog _pars _vertex >
# include < morphtarget _pars _vertex >
# include < skinning _pars _vertex >
# include < logdepthbuf _pars _vertex >
# include < clipping _planes _pars _vertex >
void main ( ) {
# include < uv _vertex >
# include < color _vertex >
# include < morphinstance _vertex >
# include < morphcolor _vertex >
# include < batching _vertex >
# if defined ( USE _ENVMAP ) || defined ( USE _SKINNING )
# include < beginnormal _vertex >
# include < morphnormal _vertex >
# include < skinbase _vertex >
# include < skinnormal _vertex >
# include < defaultnormal _vertex >
# endif
# include < begin _vertex >
# include < morphtarget _vertex >
# include < skinning _vertex >
# include < project _vertex >
# include < logdepthbuf _vertex >
# include < clipping _planes _vertex >
# include < worldpos _vertex >
# include < envmap _vertex >
# include < fog _vertex >
} ` ,meshbasic_frag: ` uniform vec3 diffuse ;
uniform float opacity ;
# ifndef FLAT _SHADED
varying vec3 vNormal ;
# endif
# include < common >
# include < dithering _pars _fragment >
# include < color _pars _fragment >
# include < uv _pars _fragment >
# include < map _pars _fragment >
# include < alphamap _pars _fragment >
# include < alphatest _pars _fragment >
# include < alphahash _pars _fragment >
# include < aomap _pars _fragment >
# include < lightmap _pars _fragment >
# include < envmap _common _pars _fragment >
# include < envmap _pars _fragment >
# include < fog _pars _fragment >
# include < specularmap _pars _fragment >
# include < logdepthbuf _pars _fragment >
# include < clipping _planes _pars _fragment >
void main ( ) {
vec4 diffuseColor = vec4 ( diffuse , opacity ) ;
# include < clipping _planes _fragment >
# include < logdepthbuf _fragment >
# include < map _fragment >
# include < color _fragment >
# include < alphamap _fragment >
# include < alphatest _fragment >
# include < alphahash _fragment >
# include < specularmap _fragment >
ReflectedLight reflectedLight = ReflectedLight ( vec3 ( 0.0 ) , vec3 ( 0.0 ) , vec3 ( 0.0 ) , vec3 ( 0.0 ) ) ;
# ifdef USE _LIGHTMAP
vec4 lightMapTexel = texture2D ( lightMap , vLightMapUv ) ;
reflectedLight . indirectDiffuse += lightMapTexel . rgb * lightMapIntensity * RECIPROCAL _PI ;
# else
reflectedLight . indirectDiffuse += vec3 ( 1.0 ) ;
# endif
# include < aomap _fragment >
reflectedLight . indirectDiffuse *= diffuseColor . rgb ;
vec3 outgoingLight = reflectedLight . indirectDiffuse ;
# include < envmap _fragment >
# include < opaque _fragment >
# include < tonemapping _fragment >
# include < colorspace _fragment >
# include < fog _fragment >
# include < premultiplied _alpha _fragment >
# include < dithering _fragment >
} ` ,meshlambert_vert: ` # define LAMBERT
varying vec3 vViewPosition ;
# include < common >
# include < batching _pars _vertex >
# include < uv _pars _vertex >
# include < displacementmap _pars _vertex >
# include < envmap _pars _vertex >
# include < color _pars _vertex >
# include < fog _pars _vertex >
# include < normal _pars _vertex >
# include < morphtarget _pars _vertex >
# include < skinning _pars _vertex >
# include < shadowmap _pars _vertex >
# include < logdepthbuf _pars _vertex >
# include < clipping _planes _pars _vertex >
void main ( ) {
# include < uv _vertex >
# include < color _vertex >
# include < morphinstance _vertex >
# include < morphcolor _vertex >
# include < batching _vertex >
# include < beginnormal _vertex >
# include < morphnormal _vertex >
# include < skinbase _vertex >
# include < skinnormal _vertex >
# include < defaultnormal _vertex >
# include < normal _vertex >
# include < begin _vertex >
# include < morphtarget _vertex >
# include < skinning _vertex >
# include < displacementmap _vertex >
# include < project _vertex >
# include < logdepthbuf _vertex >
# include < clipping _planes _vertex >
vViewPosition = - mvPosition . xyz ;
# include < worldpos _vertex >
# include < envmap _vertex >
# include < shadowmap _vertex >
# include < fog _vertex >
} ` ,meshlambert_frag: ` # define LAMBERT
uniform vec3 diffuse ;
uniform vec3 emissive ;
uniform float opacity ;
# include < common >
# include < packing >
# include < dithering _pars _fragment >
# include < color _pars _fragment >
# include < uv _pars _fragment >
# include < map _pars _fragment >
# include < alphamap _pars _fragment >
# include < alphatest _pars _fragment >
# include < alphahash _pars _fragment >
# include < aomap _pars _fragment >
# include < lightmap _pars _fragment >
# include < emissivemap _pars _fragment >
# include < envmap _common _pars _fragment >
# include < envmap _pars _fragment >
# include < fog _pars _fragment >
# include < bsdfs >
# include < lights _pars _begin >
# include < normal _pars _fragment >
# include < lights _lambert _pars _fragment >
# include < shadowmap _pars _fragment >
# include < bumpmap _pars _fragment >
# include < normalmap _pars _fragment >
# include < specularmap _pars _fragment >
# include < logdepthbuf _pars _fragment >
# include < clipping _planes _pars _fragment >
void main ( ) {
vec4 diffuseColor = vec4 ( diffuse , opacity ) ;
# include < clipping _planes _fragment >
ReflectedLight reflectedLight = ReflectedLight ( vec3 ( 0.0 ) , vec3 ( 0.0 ) , vec3 ( 0.0 ) , vec3 ( 0.0 ) ) ;
vec3 totalEmissiveRadiance = emissive ;
# include < logdepthbuf _fragment >
# include < map _fragment >
# include < color _fragment >
# include < alphamap _fragment >
# include < alphatest _fragment >
# include < alphahash _fragment >
# include < specularmap _fragment >
# include < normal _fragment _begin >
# include < normal _fragment _maps >
# include < emissivemap _fragment >
# include < lights _lambert _fragment >
# include < lights _fragment _begin >
# include < lights _fragment _maps >
# include < lights _fragment _end >
# include < aomap _fragment >
vec3 outgoingLight = reflectedLight . directDiffuse + reflectedLight . indirectDiffuse + totalEmissiveRadiance ;
# include < envmap _fragment >
# include < opaque _fragment >
# include < tonemapping _fragment >
# include < colorspace _fragment >
# include < fog _fragment >
# include < premultiplied _alpha _fragment >
# include < dithering _fragment >
} ` ,meshmatcap_vert: ` # define MATCAP
varying vec3 vViewPosition ;
# include < common >
# include < batching _pars _vertex >
# include < uv _pars _vertex >
# include < color _pars _vertex >
# include < displacementmap _pars _vertex >
# include < fog _pars _vertex >
# include < normal _pars _vertex >
# include < morphtarget _pars _vertex >
# include < skinning _pars _vertex >
# include < logdepthbuf _pars _vertex >
# include < clipping _planes _pars _vertex >
void main ( ) {
# include < uv _vertex >
# include < color _vertex >
# include < morphinstance _vertex >
# include < morphcolor _vertex >
# include < batching _vertex >
# include < beginnormal _vertex >
# include < morphnormal _vertex >
# include < skinbase _vertex >
# include < skinnormal _vertex >
# include < defaultnormal _vertex >
# include < normal _vertex >
# include < begin _vertex >
# include < morphtarget _vertex >
# include < skinning _vertex >
# include < displacementmap _vertex >
# include < project _vertex >
# include < logdepthbuf _vertex >
# include < clipping _planes _vertex >
# include < fog _vertex >
vViewPosition = - mvPosition . xyz ;
} ` ,meshmatcap_frag: ` # define MATCAP
uniform vec3 diffuse ;
uniform float opacity ;
uniform sampler2D matcap ;
varying vec3 vViewPosition ;
# include < common >
# include < dithering _pars _fragment >
# include < color _pars _fragment >
# include < uv _pars _fragment >
# include < map _pars _fragment >
# include < alphamap _pars _fragment >
# include < alphatest _pars _fragment >
# include < alphahash _pars _fragment >
# include < fog _pars _fragment >
# include < normal _pars _fragment >
# include < bumpmap _pars _fragment >
# include < normalmap _pars _fragment >
# include < logdepthbuf _pars _fragment >
# include < clipping _planes _pars _fragment >
void main ( ) {
vec4 diffuseColor = vec4 ( diffuse , opacity ) ;
# include < clipping _planes _fragment >
# include < logdepthbuf _fragment >
# include < map _fragment >
# include < color _fragment >
# include < alphamap _fragment >
# include < alphatest _fragment >
# include < alphahash _fragment >
# include < normal _fragment _begin >
# include < normal _fragment _maps >
vec3 viewDir = normalize ( vViewPosition ) ;
vec3 x = normalize ( vec3 ( viewDir . z , 0.0 , - viewDir . x ) ) ;
vec3 y = cross ( viewDir , x ) ;
vec2 uv = vec2 ( dot ( x , normal ) , dot ( y , normal ) ) * 0.495 + 0.5 ;
# ifdef USE _MATCAP
vec4 matcapColor = texture2D ( matcap , uv ) ;
# else
vec4 matcapColor = vec4 ( vec3 ( mix ( 0.2 , 0.8 , uv . y ) ) , 1.0 ) ;
# endif
vec3 outgoingLight = diffuseColor . rgb * matcapColor . rgb ;
# include < opaque _fragment >
# include < tonemapping _fragment >
# include < colorspace _fragment >
# include < fog _fragment >
# include < premultiplied _alpha _fragment >
# include < dithering _fragment >
} ` ,meshnormal_vert: ` # define NORMAL
# if defined ( FLAT _SHADED ) || defined ( USE _BUMPMAP ) || defined ( USE _NORMALMAP _TANGENTSPACE )
varying vec3 vViewPosition ;
# endif
# include < common >
# include < batching _pars _vertex >
# include < uv _pars _vertex >
# include < displacementmap _pars _vertex >
# include < normal _pars _vertex >
# include < morphtarget _pars _vertex >
# include < skinning _pars _vertex >
# include < logdepthbuf _pars _vertex >
# include < clipping _planes _pars _vertex >
void main ( ) {
# include < uv _vertex >
# include < batching _vertex >
# include < beginnormal _vertex >
# include < morphinstance _vertex >
# include < morphnormal _vertex >
# include < skinbase _vertex >
# include < skinnormal _vertex >
# include < defaultnormal _vertex >
# include < normal _vertex >
# include < begin _vertex >
# include < morphtarget _vertex >
# include < skinning _vertex >
# include < displacementmap _vertex >
# include < project _vertex >
# include < logdepthbuf _vertex >
# include < clipping _planes _vertex >
# if defined ( FLAT _SHADED ) || defined ( USE _BUMPMAP ) || defined ( USE _NORMALMAP _TANGENTSPACE )
vViewPosition = - mvPosition . xyz ;
# endif
} ` ,meshnormal_frag: ` # define NORMAL
uniform float opacity ;
# if defined ( FLAT _SHADED ) || defined ( USE _BUMPMAP ) || defined ( USE _NORMALMAP _TANGENTSPACE )
varying vec3 vViewPosition ;
# endif
# include < packing >
# include < uv _pars _fragment >
# include < normal _pars _fragment >
# include < bumpmap _pars _fragment >
# include < normalmap _pars _fragment >
# include < logdepthbuf _pars _fragment >
# include < clipping _planes _pars _fragment >
void main ( ) {
vec4 diffuseColor = vec4 ( 0.0 , 0.0 , 0.0 , opacity ) ;
# include < clipping _planes _fragment >
# include < logdepthbuf _fragment >
# include < normal _fragment _begin >
# include < normal _fragment _maps >
gl _FragColor = vec4 ( packNormalToRGB ( normal ) , diffuseColor . a ) ;
# ifdef OPAQUE
gl _FragColor . a = 1.0 ;
# endif
} ` ,meshphong_vert: ` # define PHONG
varying vec3 vViewPosition ;
# include < common >
# include < batching _pars _vertex >
# include < uv _pars _vertex >
# include < displacementmap _pars _vertex >
# include < envmap _pars _vertex >
# include < color _pars _vertex >
# include < fog _pars _vertex >
# include < normal _pars _vertex >
# include < morphtarget _pars _vertex >
# include < skinning _pars _vertex >
# include < shadowmap _pars _vertex >
# include < logdepthbuf _pars _vertex >
# include < clipping _planes _pars _vertex >
void main ( ) {
# include < uv _vertex >
# include < color _vertex >
# include < morphcolor _vertex >
# include < batching _vertex >
# include < beginnormal _vertex >
# include < morphinstance _vertex >
# include < morphnormal _vertex >
# include < skinbase _vertex >
# include < skinnormal _vertex >
# include < defaultnormal _vertex >
# include < normal _vertex >
# include < begin _vertex >
# include < morphtarget _vertex >
# include < skinning _vertex >
# include < displacementmap _vertex >
# include < project _vertex >
# include < logdepthbuf _vertex >
# include < clipping _planes _vertex >
vViewPosition = - mvPosition . xyz ;
# include < worldpos _vertex >
# include < envmap _vertex >
# include < shadowmap _vertex >
# include < fog _vertex >
} ` ,meshphong_frag: ` # define PHONG
uniform vec3 diffuse ;
uniform vec3 emissive ;
uniform vec3 specular ;
uniform float shininess ;
uniform float opacity ;
# include < common >
# include < packing >
# include < dithering _pars _fragment >
# include < color _pars _fragment >
# include < uv _pars _fragment >
# include < map _pars _fragment >
# include < alphamap _pars _fragment >
# include < alphatest _pars _fragment >
# include < alphahash _pars _fragment >
# include < aomap _pars _fragment >
# include < lightmap _pars _fragment >
# include < emissivemap _pars _fragment >
# include < envmap _common _pars _fragment >
# include < envmap _pars _fragment >
# include < fog _pars _fragment >
# include < bsdfs >
# include < lights _pars _begin >
# include < normal _pars _fragment >
# include < lights _phong _pars _fragment >
# include < shadowmap _pars _fragment >
# include < bumpmap _pars _fragment >
# include < normalmap _pars _fragment >
# include < specularmap _pars _fragment >
# include < logdepthbuf _pars _fragment >
# include < clipping _planes _pars _fragment >
void main ( ) {
vec4 diffuseColor = vec4 ( diffuse , opacity ) ;
# include < clipping _planes _fragment >
ReflectedLight reflectedLight = ReflectedLight ( vec3 ( 0.0 ) , vec3 ( 0.0 ) , vec3 ( 0.0 ) , vec3 ( 0.0 ) ) ;
vec3 totalEmissiveRadiance = emissive ;
# include < logdepthbuf _fragment >
# include < map _fragment >
# include < color _fragment >
# include < alphamap _fragment >
# include < alphatest _fragment >
# include < alphahash _fragment >
# include < specularmap _fragment >
# include < normal _fragment _begin >
# include < normal _fragment _maps >
# include < emissivemap _fragment >
# include < lights _phong _fragment >
# include < lights _fragment _begin >
# include < lights _fragment _maps >
# include < lights _fragment _end >
# include < aomap _fragment >
vec3 outgoingLight = reflectedLight . directDiffuse + reflectedLight . indirectDiffuse + reflectedLight . directSpecular + reflectedLight . indirectSpecular + totalEmissiveRadiance ;
# include < envmap _fragment >
# include < opaque _fragment >
# include < tonemapping _fragment >
# include < colorspace _fragment >
# include < fog _fragment >
# include < premultiplied _alpha _fragment >
# include < dithering _fragment >
} ` ,meshphysical_vert: ` # define STANDARD
varying vec3 vViewPosition ;
# ifdef USE _TRANSMISSION
varying vec3 vWorldPosition ;
# endif
# include < common >
# include < batching _pars _vertex >
# include < uv _pars _vertex >
# include < displacementmap _pars _vertex >
# include < color _pars _vertex >
# include < fog _pars _vertex >
# include < normal _pars _vertex >
# include < morphtarget _pars _vertex >
# include < skinning _pars _vertex >
# include < shadowmap _pars _vertex >
# include < logdepthbuf _pars _vertex >
# include < clipping _planes _pars _vertex >
void main ( ) {
# include < uv _vertex >
# include < color _vertex >
# include < morphinstance _vertex >
# include < morphcolor _vertex >
# include < batching _vertex >
# include < beginnormal _vertex >
# include < morphnormal _vertex >
# include < skinbase _vertex >
# include < skinnormal _vertex >
# include < defaultnormal _vertex >
# include < normal _vertex >
# include < begin _vertex >
# include < morphtarget _vertex >
# include < skinning _vertex >
# include < displacementmap _vertex >
# include < project _vertex >
# include < logdepthbuf _vertex >
# include < clipping _planes _vertex >
vViewPosition = - mvPosition . xyz ;
# include < worldpos _vertex >
# include < shadowmap _vertex >
# include < fog _vertex >
# ifdef USE _TRANSMISSION
vWorldPosition = worldPosition . xyz ;
# endif
} ` ,meshphysical_frag: ` # define STANDARD
# ifdef PHYSICAL
# define IOR
# define USE _SPECULAR
# endif
uniform vec3 diffuse ;
uniform vec3 emissive ;
uniform float roughness ;
uniform float metalness ;
uniform float opacity ;
# ifdef IOR
uniform float ior ;
# endif
# ifdef USE _SPECULAR
uniform float specularIntensity ;
uniform vec3 specularColor ;
# ifdef USE _SPECULAR _COLORMAP
uniform sampler2D specularColorMap ;
# endif
# ifdef USE _SPECULAR _INTENSITYMAP
uniform sampler2D specularIntensityMap ;
# endif
# endif
# ifdef USE _CLEARCOAT
uniform float clearcoat ;
uniform float clearcoatRoughness ;
# endif
# ifdef USE _DISPERSION
uniform float dispersion ;
# endif
# ifdef USE _IRIDESCENCE
uniform float iridescence ;
uniform float iridescenceIOR ;
uniform float iridescenceThicknessMinimum ;
uniform float iridescenceThicknessMaximum ;
# endif
# ifdef USE _SHEEN
uniform vec3 sheenColor ;
uniform float sheenRoughness ;
# ifdef USE _SHEEN _COLORMAP
uniform sampler2D sheenColorMap ;
# endif
# ifdef USE _SHEEN _ROUGHNESSMAP
uniform sampler2D sheenRoughnessMap ;
# endif
# endif
# ifdef USE _ANISOTROPY
uniform vec2 anisotropyVector ;
# ifdef USE _ANISOTROPYMAP
uniform sampler2D anisotropyMap ;
# endif
# endif
varying vec3 vViewPosition ;
# include < common >
# include < packing >
# include < dithering _pars _fragment >
# include < color _pars _fragment >
# include < uv _pars _fragment >
# include < map _pars _fragment >
# include < alphamap _pars _fragment >
# include < alphatest _pars _fragment >
# include < alphahash _pars _fragment >
# include < aomap _pars _fragment >
# include < lightmap _pars _fragment >
# include < emissivemap _pars _fragment >
# include < iridescence _fragment >
# include < cube _uv _reflection _fragment >
# include < envmap _common _pars _fragment >
# include < envmap _physical _pars _fragment >
# include < fog _pars _fragment >
# include < lights _pars _begin >
# include < normal _pars _fragment >
# include < lights _physical _pars _fragment >
# include < transmission _pars _fragment >
# include < shadowmap _pars _fragment >
# include < bumpmap _pars _fragment >
# include < normalmap _pars _fragment >
# include < clearcoat _pars _fragment >
# include < iridescence _pars _fragment >
# include < roughnessmap _pars _fragment >
# include < metalnessmap _pars _fragment >
# include < logdepthbuf _pars _fragment >
# include < clipping _planes _pars _fragment >
void main ( ) {
vec4 diffuseColor = vec4 ( diffuse , opacity ) ;
# include < clipping _planes _fragment >
ReflectedLight reflectedLight = ReflectedLight ( vec3 ( 0.0 ) , vec3 ( 0.0 ) , vec3 ( 0.0 ) , vec3 ( 0.0 ) ) ;
vec3 totalEmissiveRadiance = emissive ;
# include < logdepthbuf _fragment >
# include < map _fragment >
# include < color _fragment >
# include < alphamap _fragment >
# include < alphatest _fragment >
# include < alphahash _fragment >
# include < roughnessmap _fragment >
# include < metalnessmap _fragment >
# include < normal _fragment _begin >
# include < normal _fragment _maps >
# include < clearcoat _normal _fragment _begin >
# include < clearcoat _normal _fragment _maps >
# include < emissivemap _fragment >
# include < lights _physical _fragment >
# include < lights _fragment _begin >
# include < lights _fragment _maps >
# include < lights _fragment _end >
# include < aomap _fragment >
vec3 totalDiffuse = reflectedLight . directDiffuse + reflectedLight . indirectDiffuse ;
vec3 totalSpecular = reflectedLight . directSpecular + reflectedLight . indirectSpecular ;
# include < transmission _fragment >
vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance ;
# ifdef USE _SHEEN
float sheenEnergyComp = 1.0 - 0.157 * max3 ( material . sheenColor ) ;
outgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect ;
# endif
# ifdef USE _CLEARCOAT
float dotNVcc = saturate ( dot ( geometryClearcoatNormal , geometryViewDir ) ) ;
vec3 Fcc = F _Schlick ( material . clearcoatF0 , material . clearcoatF90 , dotNVcc ) ;
outgoingLight = outgoingLight * ( 1.0 - material . clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material . clearcoat ;
# endif
# include < opaque _fragment >
# include < tonemapping _fragment >
# include < colorspace _fragment >
# include < fog _fragment >
# include < premultiplied _alpha _fragment >
# include < dithering _fragment >
} ` ,meshtoon_vert: ` # define TOON
varying vec3 vViewPosition ;
# include < common >
# include < batching _pars _vertex >
# include < uv _pars _vertex >
# include < displacementmap _pars _vertex >
# include < color _pars _vertex >
# include < fog _pars _vertex >
# include < normal _pars _vertex >
# include < morphtarget _pars _vertex >
# include < skinning _pars _vertex >
# include < shadowmap _pars _vertex >
# include < logdepthbuf _pars _vertex >
# include < clipping _planes _pars _vertex >
void main ( ) {
# include < uv _vertex >
# include < color _vertex >
# include < morphinstance _vertex >
# include < morphcolor _vertex >
# include < batching _vertex >
# include < beginnormal _vertex >
# include < morphnormal _vertex >
# include < skinbase _vertex >
# include < skinnormal _vertex >
# include < defaultnormal _vertex >
# include < normal _vertex >
# include < begin _vertex >
# include < morphtarget _vertex >
# include < skinning _vertex >
# include < displacementmap _vertex >
# include < project _vertex >
# include < logdepthbuf _vertex >
# include < clipping _planes _vertex >
vViewPosition = - mvPosition . xyz ;
# include < worldpos _vertex >
# include < shadowmap _vertex >
# include < fog _vertex >
} ` ,meshtoon_frag: ` # define TOON
uniform vec3 diffuse ;
uniform vec3 emissive ;
uniform float opacity ;
# include < common >
# include < packing >
# include < dithering _pars _fragment >
# include < color _pars _fragment >
# include < uv _pars _fragment >
# include < map _pars _fragment >
# include < alphamap _pars _fragment >
# include < alphatest _pars _fragment >
# include < alphahash _pars _fragment >
# include < aomap _pars _fragment >
# include < lightmap _pars _fragment >
# include < emissivemap _pars _fragment >
# include < gradientmap _pars _fragment >
# include < fog _pars _fragment >
# include < bsdfs >
# include < lights _pars _begin >
# include < normal _pars _fragment >
# include < lights _toon _pars _fragment >
# include < shadowmap _pars _fragment >
# include < bumpmap _pars _fragment >
# include < normalmap _pars _fragment >
# include < logdepthbuf _pars _fragment >
# include < clipping _planes _pars _fragment >
void main ( ) {
vec4 diffuseColor = vec4 ( diffuse , opacity ) ;
# include < clipping _planes _fragment >
ReflectedLight reflectedLight = ReflectedLight ( vec3 ( 0.0 ) , vec3 ( 0.0 ) , vec3 ( 0.0 ) , vec3 ( 0.0 ) ) ;
vec3 totalEmissiveRadiance = emissive ;
# include < logdepthbuf _fragment >
# include < map _fragment >
# include < color _fragment >
# include < alphamap _fragment >
# include < alphatest _fragment >
# include < alphahash _fragment >
# include < normal _fragment _begin >
# include < normal _fragment _maps >
# include < emissivemap _fragment >
# include < lights _toon _fragment >
# include < lights _fragment _begin >
# include < lights _fragment _maps >
# include < lights _fragment _end >
# include < aomap _fragment >
vec3 outgoingLight = reflectedLight . directDiffuse + reflectedLight . indirectDiffuse + totalEmissiveRadiance ;
# include < opaque _fragment >
# include < tonemapping _fragment >
# include < colorspace _fragment >
# include < fog _fragment >
# include < premultiplied _alpha _fragment >
# include < dithering _fragment >
} ` ,points_vert: ` uniform float size ;
uniform float scale ;
# include < common >
# include < color _pars _vertex >
# include < fog _pars _vertex >
# include < morphtarget _pars _vertex >
# include < logdepthbuf _pars _vertex >
# include < clipping _planes _pars _vertex >
# ifdef USE _POINTS _UV
varying vec2 vUv ;
uniform mat3 uvTransform ;
# endif
void main ( ) {
# ifdef USE _POINTS _UV
vUv = ( uvTransform * vec3 ( uv , 1 ) ) . xy ;
# endif
# include < color _vertex >
# include < morphinstance _vertex >
# include < morphcolor _vertex >
# include < begin _vertex >
# include < morphtarget _vertex >
# include < project _vertex >
gl _PointSize = size ;
# ifdef USE _SIZEATTENUATION
bool isPerspective = isPerspectiveMatrix ( projectionMatrix ) ;
if ( isPerspective ) gl _PointSize *= ( scale / - mvPosition . z ) ;
# endif
# include < logdepthbuf _vertex >
# include < clipping _planes _vertex >
# include < worldpos _vertex >
# include < fog _vertex >
} ` ,points_frag: ` uniform vec3 diffuse ;
uniform float opacity ;
# include < common >
# include < color _pars _fragment >
# include < map _particle _pars _fragment >
# include < alphatest _pars _fragment >
# include < alphahash _pars _fragment >
# include < fog _pars _fragment >
# include < logdepthbuf _pars _fragment >
# include < clipping _planes _pars _fragment >
void main ( ) {
vec4 diffuseColor = vec4 ( diffuse , opacity ) ;
# include < clipping _planes _fragment >
vec3 outgoingLight = vec3 ( 0.0 ) ;
# include < logdepthbuf _fragment >
# include < map _particle _fragment >
# include < color _fragment >
# include < alphatest _fragment >
# include < alphahash _fragment >
outgoingLight = diffuseColor . rgb ;
# include < opaque _fragment >
# include < tonemapping _fragment >
# include < colorspace _fragment >
# include < fog _fragment >
# include < premultiplied _alpha _fragment >
} ` ,shadow_vert: ` # include < common >
# include < batching _pars _vertex >
# include < fog _pars _vertex >
# include < morphtarget _pars _vertex >
# include < skinning _pars _vertex >
# include < logdepthbuf _pars _vertex >
# include < shadowmap _pars _vertex >
void main ( ) {
# include < batching _vertex >
# include < beginnormal _vertex >
# include < morphinstance _vertex >
# include < morphnormal _vertex >
# include < skinbase _vertex >
# include < skinnormal _vertex >
# include < defaultnormal _vertex >
# include < begin _vertex >
# include < morphtarget _vertex >
# include < skinning _vertex >
# include < project _vertex >
# include < logdepthbuf _vertex >
# include < worldpos _vertex >
# include < shadowmap _vertex >
# include < fog _vertex >
} ` ,shadow_frag: ` uniform vec3 color ;
uniform float opacity ;
# include < common >
# include < packing >
# include < fog _pars _fragment >
# include < bsdfs >
# include < lights _pars _begin >
# include < logdepthbuf _pars _fragment >
# include < shadowmap _pars _fragment >
# include < shadowmask _pars _fragment >
void main ( ) {
# include < logdepthbuf _fragment >
gl _FragColor = vec4 ( color , opacity * ( 1.0 - getShadowMask ( ) ) ) ;
# include < tonemapping _fragment >
# include < colorspace _fragment >
# include < fog _fragment >
} ` ,sprite_vert: ` uniform float rotation ;
uniform vec2 center ;
# include < common >
# include < uv _pars _vertex >
# include < fog _pars _vertex >
# include < logdepthbuf _pars _vertex >
# include < clipping _planes _pars _vertex >
void main ( ) {
# include < uv _vertex >
vec4 mvPosition = modelViewMatrix [ 3 ] ;
vec2 scale = vec2 ( length ( modelMatrix [ 0 ] . xyz ) , length ( modelMatrix [ 1 ] . xyz ) ) ;
# ifndef USE _SIZEATTENUATION
bool isPerspective = isPerspectiveMatrix ( projectionMatrix ) ;
if ( isPerspective ) scale *= - mvPosition . z ;
# endif
vec2 alignedPosition = ( position . xy - ( center - vec2 ( 0.5 ) ) ) * scale ;
vec2 rotatedPosition ;
rotatedPosition . x = cos ( rotation ) * alignedPosition . x - sin ( rotation ) * alignedPosition . y ;
rotatedPosition . y = sin ( rotation ) * alignedPosition . x + cos ( rotation ) * alignedPosition . y ;
mvPosition . xy += rotatedPosition ;
gl _Position = projectionMatrix * mvPosition ;
# include < logdepthbuf _vertex >
# include < clipping _planes _vertex >
# include < fog _vertex >
} ` ,sprite_frag: ` uniform vec3 diffuse ;
uniform float opacity ;
# include < common >
# include < uv _pars _fragment >
# include < map _pars _fragment >
# include < alphamap _pars _fragment >
# include < alphatest _pars _fragment >
# include < alphahash _pars _fragment >
# include < fog _pars _fragment >
# include < logdepthbuf _pars _fragment >
# include < clipping _planes _pars _fragment >
void main ( ) {
vec4 diffuseColor = vec4 ( diffuse , opacity ) ;
# include < clipping _planes _fragment >
vec3 outgoingLight = vec3 ( 0.0 ) ;
# include < logdepthbuf _fragment >
# include < map _fragment >
# include < alphamap _fragment >
# include < alphatest _fragment >
# include < alphahash _fragment >
outgoingLight = diffuseColor . rgb ;
# include < opaque _fragment >
# include < tonemapping _fragment >
# include < colorspace _fragment >
# include < fog _fragment >
2026-01-28 18:40:46 +08:00
} ` },Pe={common:{diffuse:{value:new Ue(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new Ke},alphaMap:{value:null},alphaMapTransform:{value:new Ke},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new Ke}},envmap:{envMap:{value:null},envMapRotation:{value:new Ke},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98},dfgLUT:{value:null}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new Ke}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new Ke}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new Ke},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new Ke},normalScale:{value:new ce(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new Ke},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new Ke}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new Ke}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new Ke}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Ue(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new Ue(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new Ke},alphaTest:{value:0},uvTransform:{value:new Ke}},sprite:{diffuse:{value:new Ue(16777215)},opacity:{value:1},center:{value:new ce(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new Ke},alphaMap:{value:null},alphaMapTransform:{value:new Ke},alphaTest:{value:0}}},li={basic:{uniforms:an([Pe.common,Pe.specularmap,Pe.envmap,Pe.aomap,Pe.lightmap,Pe.fog]),vertexShader:et.meshbasic_vert,fragmentShader:et.meshbasic_frag},lambert:{uniforms:an([Pe.common,Pe.specularmap,Pe.envmap,Pe.aomap,Pe.lightmap,Pe.emissivemap,Pe.bumpmap,Pe.normalmap,Pe.displacementmap,Pe.fog,Pe.lights,{emissive:{value:new Ue(0)}}]),vertexShader:et.meshlambert_vert,fragmentShader:et.meshlambert_frag},phong:{uniforms:an([Pe.common,Pe.specularmap,Pe.envmap,Pe.aomap,Pe.lightmap,Pe.emissivemap,Pe.bumpmap,Pe.normalmap,Pe.displacementmap,Pe.fog,Pe.lights,{emissive:{value:new Ue(0)},specular:{value:new Ue(1118481)},shininess:{value:30}}]),vertexShader:et.meshphong_vert,fragmentShader:et.meshphong_frag},standard:{uniforms:an([Pe.common,Pe.envmap,Pe.aomap,Pe.lightmap,Pe.emissivemap,Pe.bumpmap,Pe.normalmap,Pe.displacementmap,Pe.roughnessmap,Pe.metalnessmap,Pe.fog,Pe.lights,{emissive:{value:new Ue(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:et.meshphysical_vert,fragmentShader:et.meshphysical_frag},toon:{uniforms:an([Pe.common,Pe.aomap,Pe.lightmap,Pe.emissivemap,Pe.bumpmap,Pe.normalmap,Pe.displacementmap,Pe.gradientmap,Pe.fog,Pe.lights,{emissive:{value:new Ue(0
2026-01-22 11:29:51 +08:00
precision highp float ;
precision highp int ;
varying vec3 vOutputDirection ;
uniform sampler2D envMap ;
uniform float roughness ;
uniform float mipInt ;
# define ENVMAP _TYPE _CUBE _UV
# include < cube _uv _reflection _fragment >
# define PI 3.14159265359
// Van der Corput radical inverse
float radicalInverse _VdC ( uint bits ) {
bits = ( bits << 16 u ) | ( bits >> 16 u ) ;
bits = ( ( bits & 0x55555555 u ) << 1 u ) | ( ( bits & 0xAAAAAAAA u ) >> 1 u ) ;
bits = ( ( bits & 0x33333333 u ) << 2 u ) | ( ( bits & 0xCCCCCCCC u ) >> 2 u ) ;
bits = ( ( bits & 0x0F0F0F0F u ) << 4 u ) | ( ( bits & 0xF0F0F0F0 u ) >> 4 u ) ;
bits = ( ( bits & 0x00FF00FF u ) << 8 u ) | ( ( bits & 0xFF00FF00 u ) >> 8 u ) ;
return float ( bits ) * 2.3283064365386963 e - 10 ; // / 0x100000000
}
// Hammersley sequence
vec2 hammersley ( uint i , uint N ) {
return vec2 ( float ( i ) / float ( N ) , radicalInverse _VdC ( i ) ) ;
}
// GGX VNDF importance sampling (Eric Heitz 2018)
// "Sampling the GGX Distribution of Visible Normals"
// https://jcgt.org/published/0007/04/01/
vec3 importanceSampleGGX _VNDF ( vec2 Xi , vec3 V , float roughness ) {
float alpha = roughness * roughness ;
// Section 3.2: Transform view direction to hemisphere configuration
vec3 Vh = normalize ( vec3 ( alpha * V . x , alpha * V . y , V . z ) ) ;
// Section 4.1: Orthonormal basis
float lensq = Vh . x * Vh . x + Vh . y * Vh . y ;
vec3 T1 = lensq > 0.0 ? vec3 ( - Vh . y , Vh . x , 0.0 ) / sqrt ( lensq ) : vec3 ( 1.0 , 0.0 , 0.0 ) ;
vec3 T2 = cross ( Vh , T1 ) ;
// Section 4.2: Parameterization of projected area
float r = sqrt ( Xi . x ) ;
float phi = 2.0 * PI * Xi . y ;
float t1 = r * cos ( phi ) ;
float t2 = r * sin ( phi ) ;
float s = 0.5 * ( 1.0 + Vh . z ) ;
t2 = ( 1.0 - s ) * sqrt ( 1.0 - t1 * t1 ) + s * t2 ;
// Section 4.3: Reprojection onto hemisphere
vec3 Nh = t1 * T1 + t2 * T2 + sqrt ( max ( 0.0 , 1.0 - t1 * t1 - t2 * t2 ) ) * Vh ;
// Section 3.4: Transform back to ellipsoid configuration
return normalize ( vec3 ( alpha * Nh . x , alpha * Nh . y , max ( 0.0 , Nh . z ) ) ) ;
}
void main ( ) {
vec3 N = normalize ( vOutputDirection ) ;
vec3 V = N ; // Assume view direction equals normal for pre-filtering
vec3 prefilteredColor = vec3 ( 0.0 ) ;
float totalWeight = 0.0 ;
// For very low roughness, just sample the environment directly
if ( roughness < 0.001 ) {
gl _FragColor = vec4 ( bilinearCubeUV ( envMap , N , mipInt ) , 1.0 ) ;
return ;
}
// Tangent space basis for VNDF sampling
vec3 up = abs ( N . z ) < 0.999 ? vec3 ( 0.0 , 0.0 , 1.0 ) : vec3 ( 1.0 , 0.0 , 0.0 ) ;
vec3 tangent = normalize ( cross ( up , N ) ) ;
vec3 bitangent = cross ( N , tangent ) ;
for ( uint i = 0 u ; i < uint ( GGX _SAMPLES ) ; i ++ ) {
vec2 Xi = hammersley ( i , uint ( GGX _SAMPLES ) ) ;
// For PMREM, V = N, so in tangent space V is always (0, 0, 1)
vec3 H _tangent = importanceSampleGGX _VNDF ( Xi , vec3 ( 0.0 , 0.0 , 1.0 ) , roughness ) ;
// Transform H back to world space
vec3 H = normalize ( tangent * H _tangent . x + bitangent * H _tangent . y + N * H _tangent . z ) ;
vec3 L = normalize ( 2.0 * dot ( V , H ) * H - V ) ;
float NdotL = max ( dot ( N , L ) , 0.0 ) ;
if ( NdotL > 0.0 ) {
// Sample environment at fixed mip level
// VNDF importance sampling handles the distribution filtering
vec3 sampleColor = bilinearCubeUV ( envMap , L , mipInt ) ;
// Weight by NdotL for the split-sum approximation
// VNDF PDF naturally accounts for the visible microfacet distribution
prefilteredColor += sampleColor * NdotL ;
totalWeight += NdotL ;
}
}
if ( totalWeight > 0.0 ) {
prefilteredColor = prefilteredColor / totalWeight ;
}
gl _FragColor = vec4 ( prefilteredColor , 1.0 ) ;
}
2026-01-28 18:40:46 +08:00
` ,blending:Wt,depthTest:!1,depthWrite:!1})}function ly(s,e,t){const n=new Float32Array(ms),i=new P(0,1,0);return new Ut({name:"SphericalGaussianBlur",defines:{n:ms,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/t,CUBEUV_MAX_MIP: ` $ { s } . 0 ` },uniforms:{envMap:{value:null},samples:{value:1},weights:{value:n},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:i}},vertexShader:Fa(),fragmentShader: `
2026-01-22 11:29:51 +08:00
precision mediump float ;
precision mediump int ;
varying vec3 vOutputDirection ;
uniform sampler2D envMap ;
uniform int samples ;
uniform float weights [ n ] ;
uniform bool latitudinal ;
uniform float dTheta ;
uniform float mipInt ;
uniform vec3 poleAxis ;
# define ENVMAP _TYPE _CUBE _UV
# include < cube _uv _reflection _fragment >
vec3 getSample ( float theta , vec3 axis ) {
float cosTheta = cos ( theta ) ;
// Rodrigues' axis-angle rotation
vec3 sampleDirection = vOutputDirection * cosTheta
+ cross ( axis , vOutputDirection ) * sin ( theta )
+ axis * dot ( axis , vOutputDirection ) * ( 1.0 - cosTheta ) ;
return bilinearCubeUV ( envMap , sampleDirection , mipInt ) ;
}
void main ( ) {
vec3 axis = latitudinal ? poleAxis : cross ( poleAxis , vOutputDirection ) ;
if ( all ( equal ( axis , vec3 ( 0.0 ) ) ) ) {
axis = vec3 ( vOutputDirection . z , 0.0 , - vOutputDirection . x ) ;
}
axis = normalize ( axis ) ;
gl _FragColor = vec4 ( 0.0 , 0.0 , 0.0 , 1.0 ) ;
gl _FragColor . rgb += weights [ 0 ] * getSample ( 0.0 , axis ) ;
for ( int i = 1 ; i < n ; i ++ ) {
if ( i >= samples ) {
break ;
}
float theta = dTheta * float ( i ) ;
gl _FragColor . rgb += weights [ i ] * getSample ( - 1.0 * theta , axis ) ;
gl _FragColor . rgb += weights [ i ] * getSample ( theta , axis ) ;
}
}
2026-01-28 18:40:46 +08:00
` ,blending:Wt,depthTest:!1,depthWrite:!1})}function ap(){return new Ut({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:Fa(),fragmentShader: `
2026-01-22 11:29:51 +08:00
precision mediump float ;
precision mediump int ;
varying vec3 vOutputDirection ;
uniform sampler2D envMap ;
# include < common >
void main ( ) {
vec3 outputDirection = normalize ( vOutputDirection ) ;
vec2 uv = equirectUv ( outputDirection ) ;
gl _FragColor = vec4 ( texture2D ( envMap , uv ) . rgb , 1.0 ) ;
}
2026-01-28 18:40:46 +08:00
` ,blending:Wt,depthTest:!1,depthWrite:!1})}function lp(){return new Ut({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:Fa(),fragmentShader: `
2026-01-22 11:29:51 +08:00
precision mediump float ;
precision mediump int ;
uniform float flipEnvMap ;
varying vec3 vOutputDirection ;
uniform samplerCube envMap ;
void main ( ) {
gl _FragColor = textureCube ( envMap , vec3 ( flipEnvMap * vOutputDirection . x , vOutputDirection . yz ) ) ;
}
2026-01-28 18:40:46 +08:00
` ,blending:Wt,depthTest:!1,depthWrite:!1})}function Fa(){return `
2026-01-22 11:29:51 +08:00
precision mediump float ;
precision mediump int ;
attribute float faceIndex ;
varying vec3 vOutputDirection ;
// RH coordinate system; PMREM face-indexing convention
vec3 getDirection ( vec2 uv , float face ) {
uv = 2.0 * uv - 1.0 ;
vec3 direction = vec3 ( uv , 1.0 ) ;
if ( face == 0.0 ) {
direction = direction . zyx ; // ( 1, v, u ) pos x
} else if ( face == 1.0 ) {
direction = direction . xzy ;
direction . xz *= - 1.0 ; // ( -u, 1, -v ) pos y
} else if ( face == 2.0 ) {
direction . x *= - 1.0 ; // ( -u, v, 1 ) pos z
} else if ( face == 3.0 ) {
direction = direction . zyx ;
direction . xz *= - 1.0 ; // ( -1, v, -u ) neg x
} else if ( face == 4.0 ) {
direction = direction . xzy ;
direction . xy *= - 1.0 ; // ( -u, -1, v ) neg y
} else if ( face == 5.0 ) {
direction . z *= - 1.0 ; // ( u, v, -1 ) neg z
}
return direction ;
}
void main ( ) {
vOutputDirection = getDirection ( uv , faceIndex ) ;
gl _Position = vec4 ( position , 1.0 ) ;
}
2026-01-28 18:40:46 +08:00
` }function cy(s){let e=new WeakMap,t=null;function n(a){if(a&&a.isTexture){const l=a.mapping,c=l===ec||l===tc,h=l===Fs||l===zs;if(c||h){let u=e.get(a);const d=u!==void 0?u.texture.pmremVersion:0;if(a.isRenderTargetTexture&&a.pmremVersion!==d)return t===null&&(t=new rp(s)),u=c?t.fromEquirectangular(a,u):t.fromCubemap(a,u),u.texture.pmremVersion=a.pmremVersion,e.set(a,u),u.texture;if(u!==void 0)return u.texture;{const f=a.image;return c&&f&&f.height>0||h&&f&&i(f)?(t===null&&(t=new rp(s)),u=c?t.fromEquirectangular(a):t.fromCubemap(a),u.texture.pmremVersion=a.pmremVersion,e.set(a,u),a.addEventListener("dispose",r),u.texture):null}}}return a}function i(a){let l=0;const c=6;for(let h=0;h<c;h++)a[h]!==void 0&&l++;return l===c}function r(a){const l=a.target;l.removeEventListener("dispose",r);const c=e.get(l);c!==void 0&&(e.delete(l),c.dispose())}function o(){e=new WeakMap,t!==null&&(t.dispose(),t=null)}return{get:n,dispose:o}}function hy(s){const e={};function t(n){if(e[n]!==void 0)return e[n];const i=s.getExtension(n);return e[n]=i,i}return{has:function(n){return t(n)!==null},init:function(){t("EXT_color_buffer_float"),t("WEBGL_clip_cull_distance"),t("OES_texture_float_linear"),t("EXT_color_buffer_half_float"),t("WEBGL_multisampled_render_to_texture"),t("WEBGL_render_shared_exponent")},get:function(n){const i=t(n);return i===null&& $ r("WebGLRenderer: "+n+" extension not supported."),i}}}function uy(s,e,t,n){const i={},r=new WeakMap;function o(u){const d=u.target;d.index!==null&&e.remove(d.index);for(const g in d.attributes)e.remove(d.attributes[g]);d.removeEventListener("dispose",o),delete i[d.id];const f=r.get(d);f&&(e.remove(f),r.delete(d)),n.releaseStatesOfGeometry(d),d.isInstancedBufferGeometry===!0&&delete d._maxInstanceCount,t.memory.geometries--}function a(u,d){return i[d.id]===!0||(d.addEventListener("dispose",o),i[d.id]=!0,t.memory.geometries++),d}function l(u){const d=u.attributes;for(const f in d)e.update(d[f],s.ARRAY_BUFFER)}function c(u){const d=[],f=u.index,g=u.attributes.position;let p=0;if(f!==null){const b=f.array;p=f.version;for(let v=0,y=b.length;v<y;v+=3){const M=b[v+0],E=b[v+1],A=b[v+2];d.push(M,E,E,A,A,M)}}else if(g!==void 0){const b=g.array;p=g.version;for(let v=0,y=b.length/3-1;v<y;v+=3){const M=v+0,E=v+1,A=v+2;d.push(M,E,E,A,A,M)}}else return;const x=new(Id(d)?Kd:Yd)(d,1);x.version=p;const m=r.get(u);m&&e.remove(m),r.set(u,x)}function h(u){const d=r.get(u);if(d){const f=u.index;f!==null&&d.version<f.version&&c(u)}else c(u);return r.get(u)}return{get:a,update:l,getWireframeAttribute:h}}function dy(s,e,t){let n;function i(d){n=d}let r,o;function a(d){r=d.type,o=d.bytesPerElement}function l(d,f){s.drawElements(n,f,r,d*o),t.update(f,n,1)}function c(d,f,g){g!==0&&(s.drawElementsInstanced(n,f,r,d*o,g),t.update(f,n,g))}function h(d,f,g){if(g===0)return;e.get("WEBGL_multi_draw").multiDrawElementsWEBGL(n,f,0,r,d,0,g);let x=0;for(let m=0;m<g;m++)x+=f[m];t.update(x,n,1)}function u(d,f,g,p){if(g===0)return;const x=e.get("WEBGL_multi_draw");if(x===null)for(let m=0;m<d.length;m++)c(d[m]/o,f[m],p[m]);else{x.multiDrawElementsInstancedWEBGL(n,f,0,r,d,0,p,0,g);let m=0;for(let b=0;b<g;b++)m+=f[b]*p[b];t.update(m,n,1)}}this.setMode=i,this.setIndex=a,this.render=l,this.renderInstances=c,this.renderMultiDraw=h,this.renderMultiDrawInstances=u}function fy(s){const e={geometries:0,textures:0},t={frame:0,calls:0,triangles:0,points:0,lines:0};function n(r,o,a){switch(t.calls++,o){case s.TRIANGLES:t.triangles+=a*(r/3);break;case s.LINES:t.lines+=a*(r/2);break;case s.LINE_STRIP:t.lines+=a*(r-1);break;case s.LINE_LOOP:t.lines+=a*r;break;case s.POINTS:t.points+=a*r;break;default:Qe("WebGLInfo: Unknown draw mode:",o);break}}function i(){t.calls=0,t.triangles=0,t.points=0,t.lines=0}return{memory:e,render:t,programs:null,autoReset:!0,reset:i,update:n}}function py(s,e,t){const n=new WeakMap,i=new tt;function r(o,a,l){const c=o.morphTargetInfluences,h=a.morphAttributes.position||a.morphAttributes.normal||a.morphAttributes.color,u=h!==void 0?h.length:0;let d=n.get(a);if(d===void 0||d.count!==u){let _=function(){A.dispose(),n.delete(a),a.r
2026-01-28 12:00:55 +08:00
` ),n=[],i=Math.max(e-6,0),r=Math.min(e+6,t.length);for(let o=i;o<r;o++){const a=o+1;n.push( ` $ { a === e ? ">" : " " } $ { a } : $ { t [ o ] } ` )}return n.join( `
2026-01-28 18:40:46 +08:00
` )}const _p=new Ke;function c_(s){it._getMatrix(_p,it.workingColorSpace,s);const e= ` mat3 ( $ { _p . elements . map ( t => t . toFixed ( 4 ) ) } ) ` ;switch(it.getTransfer(s)){case Jo:return[e,"LinearTransferOETF"];case lt:return[e,"sRGBTransferOETF"];default:return He("WebGLProgram: Unsupported color space: ",s),[e,"LinearTransferOETF"]}}function Mp(s,e,t){const n=s.getShaderParameter(e,s.COMPILE_STATUS),r=(s.getShaderInfoLog(e)||"").trim();if(n&&r==="")return"";const o=/ERROR: 0:( \d +)/.exec(r);if(o){const a=parseInt(o[1]);return t.toUpperCase()+ `
2026-01-22 11:29:51 +08:00
` +r+ `
2026-01-28 17:19:36 +08:00
` +l_(s.getShaderSource(e),a)}else return r}function h_(s,e){const t=c_(e);return[ ` vec4 $ { s } ( vec4 value ) { ` , ` return $ { t [ 1 ] } ( vec4 ( value . rgb * $ { t [ 0 ] } , value . a ) ) ; ` ,"}"].join( `
2026-01-28 18:40:46 +08:00
` )}function u_(s,e){let t;switch(e){case ud:t="Linear";break;case dd:t="Reinhard";break;case fd:t="Cineon";break;case Ql:t="ACESFilmic";break;case md:t="AgX";break;case gd:t="Neutral";break;case pd:t="Custom";break;default:He("WebGLProgram: Unsupported toneMapping:",e),t="Linear"}return"vec3 "+s+"( vec3 color ) { return "+t+"ToneMapping( color ); }"}const Va=new P;function d_(){it.getLuminanceCoefficients(Va);const s=Va.x.toFixed(4),e=Va.y.toFixed(4),t=Va.z.toFixed(4);return["float luminance( const in vec3 rgb ) {", ` const vec3 weights = vec3 ( $ { s } , $ { e } , $ { t } ) ; ` ," return dot( weights, rgb );","}"].join( `
2026-01-28 17:19:36 +08:00
` )}function f_(s){return[s.extensionClipCullDistance?"#extension GL_ANGLE_clip_cull_distance : require":"",s.extensionMultiDraw?"#extension GL_ANGLE_multi_draw : require":""].filter(So).join( `
` )}function p_(s){const e=[];for(const t in s){const n=s[t];n!==!1&&e.push("#define "+t+" "+n)}return e.join( `
2026-01-28 18:40:46 +08:00
` )}function m_(s,e){const t={},n=s.getProgramParameter(e,s.ACTIVE_ATTRIBUTES);for(let i=0;i<n;i++){const r=s.getActiveAttrib(e,i),o=r.name;let a=1;r.type===s.FLOAT_MAT2&&(a=2),r.type===s.FLOAT_MAT3&&(a=3),r.type===s.FLOAT_MAT4&&(a=4),t[o]={type:r.type,location:s.getAttribLocation(e,o),locationSize:a}}return t}function So(s){return s!==""}function wp(s,e){const t=e.numSpotLightShadows+e.numSpotLightMaps-e.numSpotLightShadowsWithMaps;return s.replace(/NUM_DIR_LIGHTS/g,e.numDirLights).replace(/NUM_SPOT_LIGHTS/g,e.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,e.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,t).replace(/NUM_RECT_AREA_LIGHTS/g,e.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,e.numPointLights).replace(/NUM_HEMI_LIGHTS/g,e.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,e.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,e.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,e.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,e.numPointLightShadows)}function Sp(s,e){return s.replace(/NUM_CLIPPING_PLANES/g,e.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,e.numClippingPlanes-e.numClipIntersection)}const g_=/^[ \t ]*#include +<([ \w \d ./]+)>/gm;function Gh(s){return s.replace(g_,v_)}const x_=new Map;function v_(s,e){let t=et[e];if(t===void 0){const n=x_.get(e);if(n!==void 0)t=et[n],He('WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',e,n);else throw new Error("Can not resolve #include <"+e+">")}return Gh(t)}const b_=/#pragma unroll_loop_start \s +for \s * \( \s *int \s +i \s *= \s *( \d +) \s *; \s *i \s *< \s *( \d +) \s *; \s *i \s * \+ \+ \s * \) \s *{([ \s \S ]+?)} \s +#pragma unroll_loop_end/g;function Ep(s){return s.replace(b_,y_)}function y_(s,e,t,n){let i="";for(let r=parseInt(e);r<parseInt(t);r++)i+=n.replace(/ \[ \s *i \s * \] /g,"[ "+r+" ]").replace(/UNROLLED_LOOP_INDEX/g,r);return i}function Tp(s){let e= ` precision $ { s . precision } float ;
2026-01-22 11:29:51 +08:00
precision $ { s . precision } int ;
precision $ { s . precision } sampler2D ;
precision $ { s . precision } samplerCube ;
precision $ { s . precision } sampler3D ;
precision $ { s . precision } sampler2DArray ;
precision $ { s . precision } sampler2DShadow ;
precision $ { s . precision } samplerCubeShadow ;
precision $ { s . precision } sampler2DArrayShadow ;
precision $ { s . precision } isampler2D ;
precision $ { s . precision } isampler3D ;
precision $ { s . precision } isamplerCube ;
precision $ { s . precision } isampler2DArray ;
precision $ { s . precision } usampler2D ;
precision $ { s . precision } usampler3D ;
precision $ { s . precision } usamplerCube ;
precision $ { s . precision } usampler2DArray ;
` ;return s.precision==="highp"?e+= `
# define HIGH _PRECISION ` :s.precision==="mediump"?e+= `
# define MEDIUM _PRECISION ` :s.precision==="lowp"&&(e+= `
2026-01-28 18:40:46 +08:00
# define LOW _PRECISION ` ),e}function __(s){let e="SHADOWMAP_TYPE_BASIC";return s.shadowMapType===od?e="SHADOWMAP_TYPE_PCF":s.shadowMapType===ad?e="SHADOWMAP_TYPE_PCF_SOFT":s.shadowMapType===mi&&(e="SHADOWMAP_TYPE_VSM"),e}function M_(s){let e="ENVMAP_TYPE_CUBE";if(s.envMap)switch(s.envMapMode){case Fs:case zs:e="ENVMAP_TYPE_CUBE";break;case Xo:e="ENVMAP_TYPE_CUBE_UV";break}return e}function w_(s){let e="ENVMAP_MODE_REFLECTION";if(s.envMap)switch(s.envMapMode){case zs:e="ENVMAP_MODE_REFRACTION";break}return e}function S_(s){let e="ENVMAP_BLENDING_NONE";if(s.envMap)switch(s.combine){case Wo:e="ENVMAP_BLENDING_MULTIPLY";break;case _g:e="ENVMAP_BLENDING_MIX";break;case Mg:e="ENVMAP_BLENDING_ADD";break}return e}function E_(s){const e=s.envMapCubeUVHeight;if(e===null)return null;const t=Math.log2(e)-2,n=1/e;return{texelWidth:1/(3*Math.max(Math.pow(2,t),112)),texelHeight:n,maxMip:t}}function T_(s,e,t,n){const i=s.getContext(),r=t.defines;let o=t.vertexShader,a=t.fragmentShader;const l=__(t),c=M_(t),h=w_(t),u=S_(t),d=E_(t),f=f_(t),g=p_(r),p=i.createProgram();let x,m,b=t.glslVersion?"#version "+t.glslVersion+ `
` :"";t.isRawShaderMaterial?(x=["#define SHADER_TYPE "+t.shaderType,"#define SHADER_NAME "+t.shaderName,g].filter(So).join( `
2026-01-22 11:29:51 +08:00
` ),x.length>0&&(x+= `
2026-01-28 18:40:46 +08:00
` ),m=["#define SHADER_TYPE "+t.shaderType,"#define SHADER_NAME "+t.shaderName,g].filter(So).join( `
2026-01-22 11:29:51 +08:00
` ),m.length>0&&(m+= `
2026-01-28 18:40:46 +08:00
` )):(x=[Tp(t),"#define SHADER_TYPE "+t.shaderType,"#define SHADER_NAME "+t.shaderName,g,t.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",t.batching?"#define USE_BATCHING":"",t.batchingColor?"#define USE_BATCHING_COLOR":"",t.instancing?"#define USE_INSTANCING":"",t.instancingColor?"#define USE_INSTANCING_COLOR":"",t.instancingMorph?"#define USE_INSTANCING_MORPH":"",t.useFog&&t.fog?"#define USE_FOG":"",t.useFog&&t.fogExp2?"#define FOG_EXP2":"",t.map?"#define USE_MAP":"",t.envMap?"#define USE_ENVMAP":"",t.envMap?"#define "+h:"",t.lightMap?"#define USE_LIGHTMAP":"",t.aoMap?"#define USE_AOMAP":"",t.bumpMap?"#define USE_BUMPMAP":"",t.normalMap?"#define USE_NORMALMAP":"",t.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",t.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",t.displacementMap?"#define USE_DISPLACEMENTMAP":"",t.emissiveMap?"#define USE_EMISSIVEMAP":"",t.anisotropy?"#define USE_ANISOTROPY":"",t.anisotropyMap?"#define USE_ANISOTROPYMAP":"",t.clearcoatMap?"#define USE_CLEARCOATMAP":"",t.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",t.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",t.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",t.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",t.specularMap?"#define USE_SPECULARMAP":"",t.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",t.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",t.roughnessMap?"#define USE_ROUGHNESSMAP":"",t.metalnessMap?"#define USE_METALNESSMAP":"",t.alphaMap?"#define USE_ALPHAMAP":"",t.alphaHash?"#define USE_ALPHAHASH":"",t.transmission?"#define USE_TRANSMISSION":"",t.transmissionMap?"#define USE_TRANSMISSIONMAP":"",t.thicknessMap?"#define USE_THICKNESSMAP":"",t.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",t.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",t.mapUv?"#define MAP_UV "+t.mapUv:"",t.alphaMapUv?"#define ALPHAMAP_UV "+t.alphaMapUv:"",t.lightMapUv?"#define LIGHTMAP_UV "+t.lightMapUv:"",t.aoMapUv?"#define AOMAP_UV "+t.aoMapUv:"",t.emissiveMapUv?"#define EMISSIVEMAP_UV "+t.emissiveMapUv:"",t.bumpMapUv?"#define BUMPMAP_UV "+t.bumpMapUv:"",t.normalMapUv?"#define NORMALMAP_UV "+t.normalMapUv:"",t.displacementMapUv?"#define DISPLACEMENTMAP_UV "+t.displacementMapUv:"",t.metalnessMapUv?"#define METALNESSMAP_UV "+t.metalnessMapUv:"",t.roughnessMapUv?"#define ROUGHNESSMAP_UV "+t.roughnessMapUv:"",t.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+t.anisotropyMapUv:"",t.clearcoatMapUv?"#define CLEARCOATMAP_UV "+t.clearcoatMapUv:"",t.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+t.clearcoatNormalMapUv:"",t.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+t.clearcoatRoughnessMapUv:"",t.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+t.iridescenceMapUv:"",t.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+t.iridescenceThicknessMapUv:"",t.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+t.sheenColorMapUv:"",t.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+t.sheenRoughnessMapUv:"",t.specularMapUv?"#define SPECULARMAP_UV "+t.specularMapUv:"",t.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+t.specularColorMapUv:"",t.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+t.specularIntensityMapUv:"",t.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+t.transmissionMapUv:"",t.thicknessMapUv?"#define THICKNESSMAP_UV "+t.thicknessMapUv:"",t.vertexTangents&&t.flatShading===!1?"#define USE_TANGENT":"",t.vertexColors?"#define USE_COLOR":"",t.vertexAlphas?"#define USE_COLOR_ALPHA":"",t.vertexUv1s?"#define USE_UV1":"",t.vertexUv2s?"#define USE_UV2":"",t.vertexUv3s?"#define USE_UV3":"",t.pointsUvs?"#define USE_POINTS_UV":"",t.flatShading?"#define FLAT_SHADED":"",t.skinning?"#define USE_SKINNING":"",t.morphTargets?"#define USE_MORPHTARGETS":"",t.morphNormals&&t.flatShading===!1?"#define USE_MORPHNORMALS":"",t.morphColors?"#define USE_MORPHCOLORS":"",t.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+t.morphTextureStride:"",t.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+t.morphTargetsCount:"",t.doubleSided?"#define DOUBLE_SIDED":"",
2026-01-28 12:00:55 +08:00
` ].filter(So).join( `
2026-01-28 18:40:46 +08:00
` ),m=[Tp(t),"#define SHADER_TYPE "+t.shaderType,"#define SHADER_NAME "+t.shaderName,g,t.useFog&&t.fog?"#define USE_FOG":"",t.useFog&&t.fogExp2?"#define FOG_EXP2":"",t.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",t.map?"#define USE_MAP":"",t.matcap?"#define USE_MATCAP":"",t.envMap?"#define USE_ENVMAP":"",t.envMap?"#define "+c:"",t.envMap?"#define "+h:"",t.envMap?"#define "+u:"",d?"#define CUBEUV_TEXEL_WIDTH "+d.texelWidth:"",d?"#define CUBEUV_TEXEL_HEIGHT "+d.texelHeight:"",d?"#define CUBEUV_MAX_MIP "+d.maxMip+".0":"",t.lightMap?"#define USE_LIGHTMAP":"",t.aoMap?"#define USE_AOMAP":"",t.bumpMap?"#define USE_BUMPMAP":"",t.normalMap?"#define USE_NORMALMAP":"",t.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",t.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",t.emissiveMap?"#define USE_EMISSIVEMAP":"",t.anisotropy?"#define USE_ANISOTROPY":"",t.anisotropyMap?"#define USE_ANISOTROPYMAP":"",t.clearcoat?"#define USE_CLEARCOAT":"",t.clearcoatMap?"#define USE_CLEARCOATMAP":"",t.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",t.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",t.dispersion?"#define USE_DISPERSION":"",t.iridescence?"#define USE_IRIDESCENCE":"",t.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",t.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",t.specularMap?"#define USE_SPECULARMAP":"",t.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",t.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",t.roughnessMap?"#define USE_ROUGHNESSMAP":"",t.metalnessMap?"#define USE_METALNESSMAP":"",t.alphaMap?"#define USE_ALPHAMAP":"",t.alphaTest?"#define USE_ALPHATEST":"",t.alphaHash?"#define USE_ALPHAHASH":"",t.sheen?"#define USE_SHEEN":"",t.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",t.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",t.transmission?"#define USE_TRANSMISSION":"",t.transmissionMap?"#define USE_TRANSMISSIONMAP":"",t.thicknessMap?"#define USE_THICKNESSMAP":"",t.vertexTangents&&t.flatShading===!1?"#define USE_TANGENT":"",t.vertexColors||t.instancingColor||t.batchingColor?"#define USE_COLOR":"",t.vertexAlphas?"#define USE_COLOR_ALPHA":"",t.vertexUv1s?"#define USE_UV1":"",t.vertexUv2s?"#define USE_UV2":"",t.vertexUv3s?"#define USE_UV3":"",t.pointsUvs?"#define USE_POINTS_UV":"",t.gradientMap?"#define USE_GRADIENTMAP":"",t.flatShading?"#define FLAT_SHADED":"",t.doubleSided?"#define DOUBLE_SIDED":"",t.flipSided?"#define FLIP_SIDED":"",t.shadowMapEnabled?"#define USE_SHADOWMAP":"",t.shadowMapEnabled?"#define "+l:"",t.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",t.numLightProbes>0?"#define USE_LIGHT_PROBES":"",t.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",t.decodeVideoTextureEmissive?"#define DECODE_VIDEO_TEXTURE_EMISSIVE":"",t.logarithmicDepthBuffer?"#define USE_LOGARITHMIC_DEPTH_BUFFER":"",t.reversedDepthBuffer?"#define USE_REVERSED_DEPTH_BUFFER":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",t.toneMapping!==Ni?"#define TONE_MAPPING":"",t.toneMapping!==Ni?et.tonemapping_pars_fragment:"",t.toneMapping!==Ni?u_("toneMapping",t.toneMapping):"",t.dithering?"#define DITHERING":"",t.opaque?"#define OPAQUE":"",et.colorspace_pars_fragment,h_("linearToOutputTexel",t.outputColorSpace),d_(),t.useDepthPacking?"#define DEPTH_PACKING "+t.depthPacking:"", `
2026-01-28 12:00:55 +08:00
` ].filter(So).join( `
2026-01-28 18:40:46 +08:00
` )),o=Gh(o),o=wp(o,t),o=Sp(o,t),a=Gh(a),a=wp(a,t),a=Sp(a,t),o=Ep(o),a=Ep(a),t.isRawShaderMaterial!==!0&&(b= ` # version 300 es
2026-01-28 12:00:55 +08:00
` ,x=[f,"#define attribute in","#define varying out","#define texture2D texture"].join( `
2026-01-22 11:29:51 +08:00
` )+ `
2026-01-28 18:40:46 +08:00
` +x,m=["#define varying in",t.glslVersion===Dd?"":"layout(location = 0) out highp vec4 pc_fragColor;",t.glslVersion===Dd?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join( `
2026-01-22 11:29:51 +08:00
` )+ `
2026-01-28 18:40:46 +08:00
` +m);const v=b+x+o,y=b+m+a,M=yp(i,i.VERTEX_SHADER,v),E=yp(i,i.FRAGMENT_SHADER,y);i.attachShader(p,M),i.attachShader(p,E),t.index0AttributeName!==void 0?i.bindAttribLocation(p,0,t.index0AttributeName):t.morphTargets===!0&&i.bindAttribLocation(p,0,"position"),i.linkProgram(p);function A(D){if(s.debug.checkShaderErrors){const C=i.getProgramInfoLog(p)||"",B=i.getShaderInfoLog(M)||"",w=i.getShaderInfoLog(E)||"",F=C.trim(),W=B.trim(),j=w.trim();let $ =!0,q=!0;if(i.getProgramParameter(p,i.LINK_STATUS)===!1)if( $ =!1,typeof s.debug.onShaderError=="function")s.debug.onShaderError(i,p,M,E);else{const re=Mp(i,M,"vertex"),X=Mp(i,E,"fragment");Qe("THREE.WebGLProgram: Shader Error "+i.getError()+" - VALIDATE_STATUS "+i.getProgramParameter(p,i.VALIDATE_STATUS)+ `
2026-01-22 11:29:51 +08:00
2026-01-28 12:00:55 +08:00
Material Name : ` +D.name+ `
Material Type : ` +D.type+ `
2026-01-22 11:29:51 +08:00
2026-01-28 12:00:55 +08:00
Program Info Log : ` +F+ `
` +re+ `
2026-01-28 18:40:46 +08:00
` +X)}else F!==""?He("WebGLProgram: Program Info Log:",F):(W===""||j==="")&&(q=!1);q&&(D.diagnostics={runnable: $ ,programLog:F,vertexShader:{log:W,prefix:x},fragmentShader:{log:j,prefix:m}})}i.deleteShader(M),i.deleteShader(E),R=new Ha(i,p),_=m_(i,p)}let R;this.getUniforms=function(){return R===void 0&&A(this),R};let _;this.getAttributes=function(){return _===void 0&&A(this),_};let S=t.rendererExtensionParallelShaderCompile===!1;return this.isReady=function(){return S===!1&&(S=i.getProgramParameter(p,o_)),S},this.destroy=function(){n.releaseStatesOfProgram(this),i.deleteProgram(p),this.program=void 0},this.type=t.shaderType,this.name=t.shaderName,this.id=a_++,this.cacheKey=e,this.usedTimes=1,this.program=p,this.vertexShader=M,this.fragmentShader=E,this}let A_=0;class C_{constructor(){this.shaderCache=new Map,this.materialCache=new Map}update(e){const t=e.vertexShader,n=e.fragmentShader,i=this._getShaderStage(t),r=this._getShaderStage(n),o=this._getShaderCacheForMaterial(e);return o.has(i)===!1&&(o.add(i),i.usedTimes++),o.has(r)===!1&&(o.add(r),r.usedTimes++),this}remove(e){const t=this.materialCache.get(e);for(const n of t)n.usedTimes--,n.usedTimes===0&&this.shaderCache.delete(n.code);return this.materialCache.delete(e),this}getVertexShaderID(e){return this._getShaderStage(e.vertexShader).id}getFragmentShaderID(e){return this._getShaderStage(e.fragmentShader).id}dispose(){this.shaderCache.clear(),this.materialCache.clear()}_getShaderCacheForMaterial(e){const t=this.materialCache;let n=t.get(e);return n===void 0&&(n=new Set,t.set(e,n)),n}_getShaderStage(e){const t=this.shaderCache;let n=t.get(e);return n===void 0&&(n=new P_(e),t.set(e,n)),n}}class P_{constructor(e){this.id=A_++,this.code=e,this.usedTimes=0}}function R_(s,e,t,n,i,r,o){const a=new Jc,l=new C_,c=new Set,h=[],u=i.logarithmicDepthBuffer,d=i.vertexTextures;let f=i.precision;const g={MeshDepthMaterial:"depth",MeshDistanceMaterial:"distanceRGBA",MeshNormalMaterial:"normal",MeshBasicMaterial:"basic",MeshLambertMaterial:"lambert",MeshPhongMaterial:"phong",MeshToonMaterial:"toon",MeshStandardMaterial:"physical",MeshPhysicalMaterial:"physical",MeshMatcapMaterial:"matcap",LineBasicMaterial:"basic",LineDashedMaterial:"dashed",PointsMaterial:"points",ShadowMaterial:"shadow",SpriteMaterial:"sprite"};function p(_){return c.add(_),_===0?"uv": ` uv$ { _ } ` }function x(_,S,D,C,B){const w=C.fog,F=B.geometry,W=_.isMeshStandardMaterial?C.environment:null,j=(_.isMeshStandardMaterial?t:e).get(_.envMap||W), $ =j&&j.mapping===Xo?j.image.height:null,q=g[_.type];_.precision!==null&&(f=i.getMaxPrecision(_.precision),f!==_.precision&&He("WebGLProgram.getParameters:",_.precision,"not supported, using",f,"instead."));const re=F.morphAttributes.position||F.morphAttributes.normal||F.morphAttributes.color,X=re!==void 0?re.length:0;let Y=0;F.morphAttributes.position!==void 0&&(Y=1),F.morphAttributes.normal!==void 0&&(Y=2),F.morphAttributes.color!==void 0&&(Y=3);let ge,pe,de,ie;if(q){const pt=li[q];ge=pt.vertexShader,pe=pt.fragmentShader}else ge=_.vertexShader,pe=_.fragmentShader,l.update(_),de=l.getVertexShaderID(_),ie=l.getFragmentShaderID(_);const he=s.getRenderTarget(),fe=s.state.buffers.depth.getReversed(),ve=B.isInstancedMesh===!0,we=B.isBatchedMesh===!0,Be=!!_.map,Je=!!_.matcap,Ne=!!j,T=!!_.aoMap,I=!!_.lightMap,V=!!_.bumpMap,O=!!_.normalMap,U=!!_.displacementMap,z=!!_.emissiveMap,ee=!!_.metalnessMap,J=!!_.roughnessMap,G=_.anisotropy>0,N=_.clearcoat>0,L=_.dispersion>0,H=_.iridescence>0,K=_.sheen>0,le=_.transmission>0,te=G&&!!_.anisotropyMap,Ae=N&&!!_.clearcoatMap,be=N&&!!_.clearcoatNormalMap,Re=N&&!!_.clearcoatRoughnessMap,De=H&&!!_.iridescenceMap,ue=H&&!!_.iridescenceThicknessMap,ye=K&&!!_.sheenColorMap,Ve=K&&!!_.sheenRoughnessMap,Oe=!!_.specularMap,Ce=!!_.specularColorMap,Ge=!!_.specularIntensityMap,Z=le&&!!_.transmissionMap,Ee=le&&!!_.thicknessMap,_e=!!_.gradientMap,Me=!!_.alphaMap,xe=_.alphaTest>0,me=!!_.alphaHash,Fe=!!_.extensions;let Ye=Ni;_.toneMapped&&(he===null||he.isXRRenderTarget===!0)&&(Ye=s.toneMapping);const Mt={shaderID:q,shaderType:_.type,shaderName:_.name,vertexShader:ge,fragmen
2026-01-22 11:29:51 +08:00
gl _Position = vec4 ( position , 1.0 ) ;
2026-01-28 17:19:36 +08:00
} ` ,H_= ` uniform sampler2D shadow _pass ;
2026-01-22 11:29:51 +08:00
uniform vec2 resolution ;
uniform float radius ;
# include < packing >
void main ( ) {
const float samples = float ( VSM _SAMPLES ) ;
float mean = 0.0 ;
float squared _mean = 0.0 ;
float uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 ) ;
float uvStart = samples <= 1.0 ? 0.0 : - 1.0 ;
for ( float i = 0.0 ; i < samples ; i ++ ) {
float uvOffset = uvStart + i * uvStride ;
# ifdef HORIZONTAL _PASS
vec2 distribution = unpackRGBATo2Half ( texture2D ( shadow _pass , ( gl _FragCoord . xy + vec2 ( uvOffset , 0.0 ) * radius ) / resolution ) ) ;
mean += distribution . x ;
squared _mean += distribution . y * distribution . y + distribution . x * distribution . x ;
# else
float depth = unpackRGBAToDepth ( texture2D ( shadow _pass , ( gl _FragCoord . xy + vec2 ( 0.0 , uvOffset ) * radius ) / resolution ) ) ;
mean += depth ;
squared _mean += depth * depth ;
# endif
}
mean = mean / samples ;
squared _mean = squared _mean / samples ;
float std _dev = sqrt ( squared _mean - mean * mean ) ;
gl _FragColor = pack2HalfToRGBA ( vec2 ( mean , std _dev ) ) ;
2026-01-28 18:40:46 +08:00
} ` ;function V_(s,e,t){let n=new xh;const i=new ce,r=new ce,o=new tt,a=new mv({depthPacking:Ag}),l=new gv,c={},h=t.maxTextureSize,u={[Pn]:on,[on]:Pn,[Et]:Et},d=new Ut({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new ce},radius:{value:4}},vertexShader:z_,fragmentShader:H_}),f=d.clone();f.defines.HORIZONTAL_PASS=1;const g=new ht;g.setAttribute("position",new at(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const p=new ut(g,d),x=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=od;let m=this.type;this.render=function(E,A,R){if(x.enabled===!1||x.autoUpdate===!1&&x.needsUpdate===!1||E.length===0)return;const _=s.getRenderTarget(),S=s.getActiveCubeFace(),D=s.getActiveMipmapLevel(),C=s.state;C.setBlending(Wt),C.buffers.depth.getReversed()===!0?C.buffers.color.setClear(0,0,0,0):C.buffers.color.setClear(1,1,1,1),C.buffers.depth.setTest(!0),C.setScissorTest(!1);const B=m!==mi&&this.type===mi,w=m===mi&&this.type!==mi;for(let F=0,W=E.length;F<W;F++){const j=E[F], $ =j.shadow;if( $ ===void 0){He("WebGLShadowMap:",j,"has no shadow.");continue}if( $ .autoUpdate===!1&& $ .needsUpdate===!1)continue;i.copy( $ .mapSize);const q= $ .getFrameExtents();if(i.multiply(q),r.copy( $ .mapSize),(i.x>h||i.y>h)&&(i.x>h&&(r.x=Math.floor(h/q.x),i.x=r.x*q.x, $ .mapSize.x=r.x),i.y>h&&(r.y=Math.floor(h/q.y),i.y=r.y*q.y, $ .mapSize.y=r.y)), $ .map===null||B===!0||w===!0){const X=this.type!==mi?{minFilter:Kt,magFilter:Kt}:{}; $ .map!==null&& $ .map.dispose(), $ .map=new pn(i.x,i.y,X), $ .map.texture.name=j.name+".shadowMap", $ .camera.updateProjectionMatrix()}s.setRenderTarget( $ .map),s.clear();const re= $ .getViewportCount();for(let X=0;X<re;X++){const Y= $ .getViewport(X);o.set(r.x*Y.x,r.y*Y.y,r.x*Y.z,r.y*Y.w),C.viewport(o), $ .updateMatrices(j,X),n= $ .getFrustum(),y(A,R, $ .camera,j,this.type)} $ .isPointLightShadow!==!0&&this.type===mi&&b( $ ,R), $ .needsUpdate=!1}m=this.type,x.needsUpdate=!1,s.setRenderTarget(_,S,D)};function b(E,A){const R=e.update(p);d.defines.VSM_SAMPLES!==E.blurSamples&&(d.defines.VSM_SAMPLES=E.blurSamples,f.defines.VSM_SAMPLES=E.blurSamples,d.needsUpdate=!0,f.needsUpdate=!0),E.mapPass===null&&(E.mapPass=new pn(i.x,i.y)),d.uniforms.shadow_pass.value=E.map.texture,d.uniforms.resolution.value=E.mapSize,d.uniforms.radius.value=E.radius,s.setRenderTarget(E.mapPass),s.clear(),s.renderBufferDirect(A,null,R,d,p,null),f.uniforms.shadow_pass.value=E.mapPass.texture,f.uniforms.resolution.value=E.mapSize,f.uniforms.radius.value=E.radius,s.setRenderTarget(E.map),s.clear(),s.renderBufferDirect(A,null,R,f,p,null)}function v(E,A,R,_){let S=null;const D=R.isPointLight===!0?E.customDistanceMaterial:E.customDepthMaterial;if(D!==void 0)S=D;else if(S=R.isPointLight===!0?l:a,s.localClippingEnabled&&A.clipShadows===!0&&Array.isArray(A.clippingPlanes)&&A.clippingPlanes.length!==0||A.displacementMap&&A.displacementScale!==0||A.alphaMap&&A.alphaTest>0||A.map&&A.alphaTest>0||A.alphaToCoverage===!0){const C=S.uuid,B=A.uuid;let w=c[C];w===void 0&&(w={},c[C]=w);let F=w[B];F===void 0&&(F=S.clone(),w[B]=F,A.addEventListener("dispose",M)),S=F}if(S.visible=A.visible,S.wireframe=A.wireframe,_===mi?S.side=A.shadowSide!==null?A.shadowSide:A.side:S.side=A.shadowSide!==null?A.shadowSide:u[A.side],S.alphaMap=A.alphaMap,S.alphaTest=A.alphaToCoverage===!0?.5:A.alphaTest,S.map=A.map,S.clipShadows=A.clipShadows,S.clippingPlanes=A.clippingPlanes,S.clipIntersection=A.clipIntersection,S.displacementMap=A.displacementMap,S.displacementScale=A.displacementScale,S.displacementBias=A.displacementBias,S.wireframeLinewidth=A.wireframeLinewidth,S.linewidth=A.linewidth,R.isPointLight===!0&&S.isMeshDistanceMaterial===!0){const C=s.properties.get(S);C.light=R}return S}function y(E,A,R,_,S){if(E.visible===!1)return;if(E.layers.test(A.layers)&&(E.isMesh||E.isLine||E.isPoints)&&(E.castShadow||E.receiveShadow&&S===mi)&&(!E.frustumCulled||n.intersectsObject(E))){E.modelViewMatrix.multiplyMatrices(R.matrixWorldInverse,E.matrixWorld);const B=e.update(E),w=E.material;if(Array.isArray(w)){const F=B.groups;for(let W=0,j=F.length;W<j;W++){const $ =F[W],q=w[ $ .materialIndex];if(q&&q.visible
2026-01-22 11:29:51 +08:00
void main ( ) {
gl _Position = vec4 ( position , 1.0 ) ;
2026-01-28 18:40:46 +08:00
} ` ,q_= `
2026-01-22 11:29:51 +08:00
uniform sampler2DArray depthColor ;
uniform float depthWidth ;
uniform float depthHeight ;
void main ( ) {
vec2 coord = vec2 ( gl _FragCoord . x / depthWidth , gl _FragCoord . y / depthHeight ) ;
if ( coord . x >= 1.0 ) {
gl _FragDepth = texture ( depthColor , vec3 ( coord . x - 1.0 , coord . y , 1 ) ) . r ;
} else {
gl _FragDepth = texture ( depthColor , vec3 ( coord . x , coord . y , 0 ) ) . r ;
}
2026-01-28 18:40:46 +08:00
} ` ;class Y_{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(e,t){if(this.texture===null){const n=new Cf(e.texture);(e.depthNear!==t.depthNear||e.depthFar!==t.depthFar)&&(this.depthNear=e.depthNear,this.depthFar=e.depthFar),this.texture=n}}getMesh(e){if(this.texture!==null&&this.mesh===null){const t=e.cameras[0].viewport,n=new Ut({vertexShader:Z_,fragmentShader:q_,uniforms:{depthColor:{value:this.texture},depthWidth:{value:t.z},depthHeight:{value:t.w}}});this.mesh=new ut(new bo(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}}class K_ extends ns{constructor(e,t){super();const n=this;let i=null,r=1,o=null,a="local-floor",l=1,c=null,h=null,u=null,d=null,f=null,g=null;const p=typeof XRWebGLBinding<"u",x=new Y_,m={},b=t.getContextAttributes();let v=null,y=null;const M=[],E=[],A=new ce;let R=null;const _=new sn;_.viewport=new tt;const S=new sn;S.viewport=new tt;const D=[_,S],C=new Uv;let B=null,w=null;this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(ie){let he=M[ie];return he===void 0&&(he=new hh,M[ie]=he),he.getTargetRaySpace()},this.getControllerGrip=function(ie){let he=M[ie];return he===void 0&&(he=new hh,M[ie]=he),he.getGripSpace()},this.getHand=function(ie){let he=M[ie];return he===void 0&&(he=new hh,M[ie]=he),he.getHandSpace()};function F(ie){const he=E.indexOf(ie.inputSource);if(he===-1)return;const fe=M[he];fe!==void 0&&(fe.update(ie.inputSource,ie.frame,c||o),fe.dispatchEvent({type:ie.type,data:ie.inputSource}))}function W(){i.removeEventListener("select",F),i.removeEventListener("selectstart",F),i.removeEventListener("selectend",F),i.removeEventListener("squeeze",F),i.removeEventListener("squeezestart",F),i.removeEventListener("squeezeend",F),i.removeEventListener("end",W),i.removeEventListener("inputsourceschange",j);for(let ie=0;ie<M.length;ie++){const he=E[ie];he!==null&&(E[ie]=null,M[ie].disconnect(he))}B=null,w=null,x.reset();for(const ie in m)delete m[ie];e.setRenderTarget(v),f=null,d=null,u=null,i=null,y=null,de.stop(),n.isPresenting=!1,e.setPixelRatio(R),e.setSize(A.width,A.height,!1),n.dispatchEvent({type:"sessionend"})}this.setFramebufferScaleFactor=function(ie){r=ie,n.isPresenting===!0&&He("WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(ie){a=ie,n.isPresenting===!0&&He("WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return c||o},this.setReferenceSpace=function(ie){c=ie},this.getBaseLayer=function(){return d!==null?d:f},this.getBinding=function(){return u===null&&p&&(u=new XRWebGLBinding(i,t)),u},this.getFrame=function(){return g},this.getSession=function(){return i},this.setSession=async function(ie){if(i=ie,i!==null){if(v=e.getRenderTarget(),i.addEventListener("select",F),i.addEventListener("selectstart",F),i.addEventListener("selectend",F),i.addEventListener("squeeze",F),i.addEventListener("squeezestart",F),i.addEventListener("squeezeend",F),i.addEventListener("end",W),i.addEventListener("inputsourceschange",j),b.xrCompatible!==!0&&await t.makeXRCompatible(),R=e.getPixelRatio(),e.getSize(A),p&&"createProjectionLayer"in XRWebGLBinding.prototype){let fe=null,ve=null,we=null;b.depth&&(we=b.stencil?t.DEPTH24_STENCIL8:t.DEPTH_COMPONENT24,fe=b.stencil?Vs:jr,ve=b.stencil?Hs:ts);const Be={colorFormat:t.RGBA8,depthFormat:we,scaleFactor:r};u=this.getBinding(),d=u.createProjectionLayer(Be),i.updateRenderState({layers:[d]}),e.setPixelRatio(1),e.setSize(d.textureWidth,d.textureHeight,!1),y=new pn(d.textureWidth,d.textureHeight,{format:fn,type:Wn,depthTexture:new yh(d.textureWidth,d.textureHeight,ve,void 0,void 0,void 0,void 0,void 0,void 0,fe),stencilBuffer:b.stencil,colorSpace:e.outputColorSpace,samples:b.antialias?4:0,resolveDepthBuffer:d.ignoreDepthValues===!1,resolveStencilBuffer:d.ignoreDepthValues===!1})}else{const fe={antialias:b.antialias,alpha:!0,depth:b.depth,stencil:b.stencil,framebufferScaleFactor:r};f=new XRWebGLLayer(i,t,fe),i.updateRenderState({baseLayer:f}
2026-01-22 11:29:51 +08:00
varying vec2 vUv ;
void main ( ) {
vUv = uv ;
gl _Position = projectionMatrix * modelViewMatrix * vec4 ( position , 1.0 ) ;
} ` ,fragmentShader: `
uniform float opacity ;
uniform sampler2D tDiffuse ;
varying vec2 vUv ;
void main ( ) {
vec4 texel = texture2D ( tDiffuse , vUv ) ;
gl _FragColor = opacity * texel ;
2026-01-28 18:40:46 +08:00
} ` };class vs{constructor(){this.isPass=!0,this.enabled=!0,this.needsSwap=!0,this.clear=!1,this.renderToScreen=!1}setSize(){}render(){console.error("THREE.Pass: .render() must be implemented in derived pass.")}dispose(){}}const _2=new ds(-1,1,1,-1,0,1);class M2 extends ht{constructor(){super(),this.setAttribute("position",new nn([-1,3,0,-1,-1,0,3,-1,0],3)),this.setAttribute("uv",new nn([0,2,0,0,2,0],2))}}const w2=new M2;class Wa{constructor(e){this._mesh=new ut(w2,e)}dispose(){this._mesh.geometry.dispose()}render(e){e.render(this._mesh,_2)}get material(){return this._mesh.material}set material(e){this._mesh.material=e}}class Xa extends vs{constructor(e,t="tDiffuse"){super(),this.textureID=t,this.uniforms=null,this.material=null,e instanceof Ut?(this.uniforms=e.uniforms,this.material=e):e&&(this.uniforms=oi.clone(e.uniforms),this.material=new Ut({name:e.name!==void 0?e.name:"unspecified",defines:Object.assign({},e.defines),uniforms:this.uniforms,vertexShader:e.vertexShader,fragmentShader:e.fragmentShader})),this._fsQuad=new Wa(this.material)}render(e,t,n){this.uniforms[this.textureID]&&(this.uniforms[this.textureID].value=n.texture),this._fsQuad.material=this.material,this.renderToScreen?(e.setRenderTarget(null),this._fsQuad.render(e)):(e.setRenderTarget(t),this.clear&&e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil),this._fsQuad.render(e))}dispose(){this.material.dispose(),this._fsQuad.dispose()}}class Np extends vs{constructor(e,t){super(),this.scene=e,this.camera=t,this.clear=!0,this.needsSwap=!1,this.inverse=!1}render(e,t,n){const i=e.getContext(),r=e.state;r.buffers.color.setMask(!1),r.buffers.depth.setMask(!1),r.buffers.color.setLocked(!0),r.buffers.depth.setLocked(!0);let o,a;this.inverse?(o=0,a=1):(o=1,a=0),r.buffers.stencil.setTest(!0),r.buffers.stencil.setOp(i.REPLACE,i.REPLACE,i.REPLACE),r.buffers.stencil.setFunc(i.ALWAYS,o,4294967295),r.buffers.stencil.setClear(a),r.buffers.stencil.setLocked(!0),e.setRenderTarget(n),this.clear&&e.clear(),e.render(this.scene,this.camera),e.setRenderTarget(t),this.clear&&e.clear(),e.render(this.scene,this.camera),r.buffers.color.setLocked(!1),r.buffers.depth.setLocked(!1),r.buffers.color.setMask(!0),r.buffers.depth.setMask(!0),r.buffers.stencil.setLocked(!1),r.buffers.stencil.setFunc(i.EQUAL,1,4294967295),r.buffers.stencil.setOp(i.KEEP,i.KEEP,i.KEEP),r.buffers.stencil.setLocked(!0)}}class S2 extends vs{constructor(){super(),this.needsSwap=!1}render(e){e.state.buffers.stencil.setLocked(!1),e.state.buffers.stencil.setTest(!1)}}class E2{constructor(e,t){if(this.renderer=e,this._pixelRatio=e.getPixelRatio(),t===void 0){const n=e.getSize(new ce);this._width=n.width,this._height=n.height,t=new pn(this._width*this._pixelRatio,this._height*this._pixelRatio,{type:Rn}),t.texture.name="EffectComposer.rt1"}else this._width=t.width,this._height=t.height;this.renderTarget1=t,this.renderTarget2=t.clone(),this.renderTarget2.texture.name="EffectComposer.rt2",this.writeBuffer=this.renderTarget1,this.readBuffer=this.renderTarget2,this.renderToScreen=!0,this.passes=[],this.copyPass=new Xa(xs),this.copyPass.material.blending=Wt,this.clock=new Ov}swapBuffers(){const e=this.readBuffer;this.readBuffer=this.writeBuffer,this.writeBuffer=e}addPass(e){this.passes.push(e),e.setSize(this._width*this._pixelRatio,this._height*this._pixelRatio)}insertPass(e,t){this.passes.splice(t,0,e),e.setSize(this._width*this._pixelRatio,this._height*this._pixelRatio)}removePass(e){const t=this.passes.indexOf(e);t!==-1&&this.passes.splice(t,1)}isLastEnabledPass(e){for(let t=e+1;t<this.passes.length;t++)if(this.passes[t].enabled)return!1;return!0}render(e){e===void 0&&(e=this.clock.getDelta());const t=this.renderer.getRenderTarget();let n=!1;for(let i=0,r=this.passes.length;i<r;i++){const o=this.passes[i];if(o.enabled!==!1){if(o.renderToScreen=this.renderToScreen&&this.isLastEnabledPass(i),o.render(this.renderer,this.writeBuffer,this.readBuffer,e,n),o.needsSwap){if(n){const a=this.renderer.getContext(),l=this.renderer.state.buffers.stencil;l.setFunc(a.NOTEQUAL,1,4294967295),this.copyPass.render(this.renderer,th
2026-01-22 11:29:51 +08:00
varying vec2 vUv ;
void main ( ) {
vUv = uv ;
gl _Position = projectionMatrix * modelViewMatrix * vec4 ( position , 1.0 ) ;
} ` ,fragmentShader: `
varying vec2 vUv ;
uniform highp sampler2D tNormal ;
uniform highp sampler2D tDepth ;
uniform sampler2D tNoise ;
uniform vec2 resolution ;
uniform float cameraNear ;
uniform float cameraFar ;
uniform mat4 cameraProjectionMatrix ;
uniform mat4 cameraProjectionMatrixInverse ;
uniform mat4 cameraWorldMatrix ;
uniform float radius ;
uniform float distanceExponent ;
uniform float thickness ;
uniform float distanceFallOff ;
uniform float scale ;
# if SCENE _CLIP _BOX == 1
uniform vec3 sceneBoxMin ;
uniform vec3 sceneBoxMax ;
# endif
# include < common >
# include < packing >
# ifndef FRAGMENT _OUTPUT
# define FRAGMENT _OUTPUT vec4 ( vec3 ( ao ) , 1. )
# endif
vec3 getViewPosition ( const in vec2 screenPosition , const in float depth ) {
vec4 clipSpacePosition = vec4 ( vec3 ( screenPosition , depth ) * 2.0 - 1.0 , 1.0 ) ;
vec4 viewSpacePosition = cameraProjectionMatrixInverse * clipSpacePosition ;
return viewSpacePosition . xyz / viewSpacePosition . w ;
}
float getDepth ( const vec2 uv ) {
return textureLod ( tDepth , uv . xy , 0.0 ) . DEPTH _SWIZZLING ;
}
float fetchDepth ( const ivec2 uv ) {
return texelFetch ( tDepth , uv . xy , 0 ) . DEPTH _SWIZZLING ;
}
float getViewZ ( const in float depth ) {
# if PERSPECTIVE _CAMERA == 1
return perspectiveDepthToViewZ ( depth , cameraNear , cameraFar ) ;
# else
return orthographicDepthToViewZ ( depth , cameraNear , cameraFar ) ;
# endif
}
vec3 computeNormalFromDepth ( const vec2 uv ) {
vec2 size = vec2 ( textureSize ( tDepth , 0 ) ) ;
ivec2 p = ivec2 ( uv * size ) ;
float c0 = fetchDepth ( p ) ;
float l2 = fetchDepth ( p - ivec2 ( 2 , 0 ) ) ;
float l1 = fetchDepth ( p - ivec2 ( 1 , 0 ) ) ;
float r1 = fetchDepth ( p + ivec2 ( 1 , 0 ) ) ;
float r2 = fetchDepth ( p + ivec2 ( 2 , 0 ) ) ;
float b2 = fetchDepth ( p - ivec2 ( 0 , 2 ) ) ;
float b1 = fetchDepth ( p - ivec2 ( 0 , 1 ) ) ;
float t1 = fetchDepth ( p + ivec2 ( 0 , 1 ) ) ;
float t2 = fetchDepth ( p + ivec2 ( 0 , 2 ) ) ;
float dl = abs ( ( 2.0 * l1 - l2 ) - c0 ) ;
float dr = abs ( ( 2.0 * r1 - r2 ) - c0 ) ;
float db = abs ( ( 2.0 * b1 - b2 ) - c0 ) ;
float dt = abs ( ( 2.0 * t1 - t2 ) - c0 ) ;
vec3 ce = getViewPosition ( uv , c0 ) . xyz ;
vec3 dpdx = ( dl < dr ) ? ce - getViewPosition ( ( uv - vec2 ( 1.0 / size . x , 0.0 ) ) , l1 ) . xyz : - ce + getViewPosition ( ( uv + vec2 ( 1.0 / size . x , 0.0 ) ) , r1 ) . xyz ;
vec3 dpdy = ( db < dt ) ? ce - getViewPosition ( ( uv - vec2 ( 0.0 , 1.0 / size . y ) ) , b1 ) . xyz : - ce + getViewPosition ( ( uv + vec2 ( 0.0 , 1.0 / size . y ) ) , t1 ) . xyz ;
return normalize ( cross ( dpdx , dpdy ) ) ;
}
vec3 getViewNormal ( const vec2 uv ) {
# if NORMAL _VECTOR _TYPE == 2
return normalize ( textureLod ( tNormal , uv , 0. ) . rgb ) ;
# elif NORMAL _VECTOR _TYPE == 1
return unpackRGBToNormal ( textureLod ( tNormal , uv , 0. ) . rgb ) ;
# else
return computeNormalFromDepth ( uv ) ;
# endif
}
vec3 getSceneUvAndDepth ( vec3 sampleViewPos ) {
vec4 sampleClipPos = cameraProjectionMatrix * vec4 ( sampleViewPos , 1. ) ;
vec2 sampleUv = sampleClipPos . xy / sampleClipPos . w * 0.5 + 0.5 ;
float sampleSceneDepth = getDepth ( sampleUv ) ;
return vec3 ( sampleUv , sampleSceneDepth ) ;
}
void main ( ) {
float depth = getDepth ( vUv . xy ) ;
if ( depth >= 1.0 ) {
discard ;
return ;
}
vec3 viewPos = getViewPosition ( vUv , depth ) ;
vec3 viewNormal = getViewNormal ( vUv ) ;
float radiusToUse = radius ;
float distanceFalloffToUse = thickness ;
# if SCREEN _SPACE _RADIUS == 1
float radiusScale = getViewPosition ( vec2 ( 0.5 + float ( SCREEN _SPACE _RADIUS _SCALE ) / resolution . x , 0.0 ) , depth ) . x ;
radiusToUse *= radiusScale ;
distanceFalloffToUse *= radiusScale ;
# endif
# if SCENE _CLIP _BOX == 1
vec3 worldPos = ( cameraWorldMatrix * vec4 ( viewPos , 1.0 ) ) . xyz ;
float boxDistance = length ( max ( vec3 ( 0.0 ) , max ( sceneBoxMin - worldPos , worldPos - sceneBoxMax ) ) ) ;
if ( boxDistance > radiusToUse ) {
discard ;
return ;
}
# endif
vec2 noiseResolution = vec2 ( textureSize ( tNoise , 0 ) ) ;
vec2 noiseUv = vUv * resolution / noiseResolution ;
vec4 noiseTexel = textureLod ( tNoise , noiseUv , 0.0 ) ;
vec3 randomVec = noiseTexel . xyz * 2.0 - 1.0 ;
vec3 tangent = normalize ( vec3 ( randomVec . xy , 0. ) ) ;
vec3 bitangent = vec3 ( - tangent . y , tangent . x , 0. ) ;
mat3 kernelMatrix = mat3 ( tangent , bitangent , vec3 ( 0. , 0. , 1. ) ) ;
const int DIRECTIONS = SAMPLES < 30 ? 3 : 5 ;
const int STEPS = ( SAMPLES + DIRECTIONS - 1 ) / DIRECTIONS ;
float ao = 0.0 ;
for ( int i = 0 ; i < DIRECTIONS ; ++ i ) {
float angle = float ( i ) / float ( DIRECTIONS ) * PI ;
vec4 sampleDir = vec4 ( cos ( angle ) , sin ( angle ) , 0. , 0.5 + 0.5 * noiseTexel . w ) ;
sampleDir . xyz = normalize ( kernelMatrix * sampleDir . xyz ) ;
vec3 viewDir = normalize ( - viewPos . xyz ) ;
vec3 sliceBitangent = normalize ( cross ( sampleDir . xyz , viewDir ) ) ;
vec3 sliceTangent = cross ( sliceBitangent , viewDir ) ;
vec3 normalInSlice = normalize ( viewNormal - sliceBitangent * dot ( viewNormal , sliceBitangent ) ) ;
vec3 tangentToNormalInSlice = cross ( normalInSlice , sliceBitangent ) ;
vec2 cosHorizons = vec2 ( dot ( viewDir , tangentToNormalInSlice ) , dot ( viewDir , - tangentToNormalInSlice ) ) ;
for ( int j = 0 ; j < STEPS ; ++ j ) {
vec3 sampleViewOffset = sampleDir . xyz * radiusToUse * sampleDir . w * pow ( float ( j + 1 ) / float ( STEPS ) , distanceExponent ) ;
vec3 sampleSceneUvDepth = getSceneUvAndDepth ( viewPos + sampleViewOffset ) ;
vec3 sampleSceneViewPos = getViewPosition ( sampleSceneUvDepth . xy , sampleSceneUvDepth . z ) ;
vec3 viewDelta = sampleSceneViewPos - viewPos ;
if ( abs ( viewDelta . z ) < thickness ) {
float sampleCosHorizon = dot ( viewDir , normalize ( viewDelta ) ) ;
cosHorizons . x += max ( 0. , ( sampleCosHorizon - cosHorizons . x ) * mix ( 1. , 2. / float ( j + 2 ) , distanceFallOff ) ) ;
}
sampleSceneUvDepth = getSceneUvAndDepth ( viewPos - sampleViewOffset ) ;
sampleSceneViewPos = getViewPosition ( sampleSceneUvDepth . xy , sampleSceneUvDepth . z ) ;
viewDelta = sampleSceneViewPos - viewPos ;
if ( abs ( viewDelta . z ) < thickness ) {
float sampleCosHorizon = dot ( viewDir , normalize ( viewDelta ) ) ;
cosHorizons . y += max ( 0. , ( sampleCosHorizon - cosHorizons . y ) * mix ( 1. , 2. / float ( j + 2 ) , distanceFallOff ) ) ;
}
}
vec2 sinHorizons = sqrt ( 1. - cosHorizons * cosHorizons ) ;
float nx = dot ( normalInSlice , sliceTangent ) ;
float ny = dot ( normalInSlice , viewDir ) ;
float nxb = 1. / 2. * ( acos ( cosHorizons . y ) - acos ( cosHorizons . x ) + sinHorizons . x * cosHorizons . x - sinHorizons . y * cosHorizons . y ) ;
float nyb = 1. / 2. * ( 2. - cosHorizons . x * cosHorizons . x - cosHorizons . y * cosHorizons . y ) ;
float occlusion = nx * nxb + ny * nyb ;
ao += occlusion ;
}
ao = clamp ( ao / float ( DIRECTIONS ) , 0. , 1. ) ;
# if SCENE _CLIP _BOX == 1
ao = mix ( ao , 1. , smoothstep ( 0. , radiusToUse , boxDistance ) ) ;
# endif
ao = pow ( ao , scale ) ;
gl _FragColor = FRAGMENT _OUTPUT ;
2026-01-28 18:40:46 +08:00
} ` },Za={defines:{PERSPECTIVE_CAMERA:1},uniforms:{tDepth:{value:null},cameraNear:{value:null},cameraFar:{value:null}},vertexShader: `
2026-01-22 11:29:51 +08:00
varying vec2 vUv ;
void main ( ) {
vUv = uv ;
gl _Position = projectionMatrix * modelViewMatrix * vec4 ( position , 1.0 ) ;
} ` ,fragmentShader: `
uniform sampler2D tDepth ;
uniform float cameraNear ;
uniform float cameraFar ;
varying vec2 vUv ;
# include < packing >
float getLinearDepth ( const in vec2 screenPosition ) {
# if PERSPECTIVE _CAMERA == 1
float fragCoordZ = texture2D ( tDepth , screenPosition ) . x ;
float viewZ = perspectiveDepthToViewZ ( fragCoordZ , cameraNear , cameraFar ) ;
return viewZToOrthographicDepth ( viewZ , cameraNear , cameraFar ) ;
# else
return texture2D ( tDepth , screenPosition ) . x ;
# endif
}
void main ( ) {
float depth = getLinearDepth ( vUv ) ;
gl _FragColor = vec4 ( vec3 ( 1.0 - depth ) , 1.0 ) ;
2026-01-28 12:00:55 +08:00
} ` },Zh={uniforms:{tDiffuse:{value:null},intensity:{value:1}},vertexShader: `
2026-01-22 11:29:51 +08:00
varying vec2 vUv ;
void main ( ) {
vUv = uv ;
gl _Position = projectionMatrix * modelViewMatrix * vec4 ( position , 1.0 ) ;
} ` ,fragmentShader: `
uniform float intensity ;
uniform sampler2D tDiffuse ;
varying vec2 vUv ;
void main ( ) {
vec4 texel = texture2D ( tDiffuse , vUv ) ;
gl _FragColor = vec4 ( mix ( vec3 ( 1. ) , texel . rgb , intensity ) , texel . a ) ;
2026-01-28 18:40:46 +08:00
} ` };function A2(s=5){const e=Math.floor(s)%2===0?Math.floor(s)+1:Math.floor(s),t=C2(e),n=t.length,i=new Uint8Array(n*4);for(let o=0;o<n;++o){const a=t[o],l=2*Math.PI*a/n,c=new P(Math.cos(l),Math.sin(l),0).normalize();i[o*4]=(c.x*.5+.5)*255,i[o*4+1]=(c.y*.5+.5)*255,i[o*4+2]=127,i[o*4+3]=255}const r=new lo(i,e,e);return r.wrapS=ni,r.wrapT=ni,r.needsUpdate=!0,r}function C2(s){const e=Math.floor(s)%2===0?Math.floor(s)+1:Math.floor(s),t=e*e,n=Array(t).fill(0);let i=Math.floor(e/2),r=e-1;for(let o=1;o<=t;){if(i===-1&&r===e?(r=e-2,i=0):(r===e&&(r=0),i<0&&(i=e-1)),n[i*e+r]!==0){r-=2,i++;continue}else n[i*e+r]=o++;r++,i--}return n}const qa={defines:{SAMPLES:16,SAMPLE_VECTORS:Up(16,2,1),NORMAL_VECTOR_TYPE:1,DEPTH_VALUE_SOURCE:0},uniforms:{tDiffuse:{value:null},tNormal:{value:null},tDepth:{value:null},tNoise:{value:null},resolution:{value:new ce},cameraProjectionMatrixInverse:{value:new ke},lumaPhi:{value:5},depthPhi:{value:5},normalPhi:{value:5},radius:{value:4},index:{value:0}},vertexShader: `
2026-01-22 11:29:51 +08:00
varying vec2 vUv ;
void main ( ) {
vUv = uv ;
gl _Position = projectionMatrix * modelViewMatrix * vec4 ( position , 1.0 ) ;
} ` ,fragmentShader: `
varying vec2 vUv ;
uniform sampler2D tDiffuse ;
uniform sampler2D tNormal ;
uniform sampler2D tDepth ;
uniform sampler2D tNoise ;
uniform vec2 resolution ;
uniform mat4 cameraProjectionMatrixInverse ;
uniform float lumaPhi ;
uniform float depthPhi ;
uniform float normalPhi ;
uniform float radius ;
uniform int index ;
# include < common >
# include < packing >
# ifndef SAMPLE _LUMINANCE
# define SAMPLE _LUMINANCE dot ( vec3 ( 0.2125 , 0.7154 , 0.0721 ) , a )
# endif
# ifndef FRAGMENT _OUTPUT
# define FRAGMENT _OUTPUT vec4 ( denoised , 1. )
# endif
float getLuminance ( const in vec3 a ) {
return SAMPLE _LUMINANCE ;
}
const vec3 poissonDisk [ SAMPLES ] = SAMPLE _VECTORS ;
vec3 getViewPosition ( const in vec2 screenPosition , const in float depth ) {
vec4 clipSpacePosition = vec4 ( vec3 ( screenPosition , depth ) * 2.0 - 1.0 , 1.0 ) ;
vec4 viewSpacePosition = cameraProjectionMatrixInverse * clipSpacePosition ;
return viewSpacePosition . xyz / viewSpacePosition . w ;
}
float getDepth ( const vec2 uv ) {
# if DEPTH _VALUE _SOURCE == 1
return textureLod ( tDepth , uv . xy , 0.0 ) . a ;
# else
return textureLod ( tDepth , uv . xy , 0.0 ) . r ;
# endif
}
float fetchDepth ( const ivec2 uv ) {
# if DEPTH _VALUE _SOURCE == 1
return texelFetch ( tDepth , uv . xy , 0 ) . a ;
# else
return texelFetch ( tDepth , uv . xy , 0 ) . r ;
# endif
}
vec3 computeNormalFromDepth ( const vec2 uv ) {
vec2 size = vec2 ( textureSize ( tDepth , 0 ) ) ;
ivec2 p = ivec2 ( uv * size ) ;
float c0 = fetchDepth ( p ) ;
float l2 = fetchDepth ( p - ivec2 ( 2 , 0 ) ) ;
float l1 = fetchDepth ( p - ivec2 ( 1 , 0 ) ) ;
float r1 = fetchDepth ( p + ivec2 ( 1 , 0 ) ) ;
float r2 = fetchDepth ( p + ivec2 ( 2 , 0 ) ) ;
float b2 = fetchDepth ( p - ivec2 ( 0 , 2 ) ) ;
float b1 = fetchDepth ( p - ivec2 ( 0 , 1 ) ) ;
float t1 = fetchDepth ( p + ivec2 ( 0 , 1 ) ) ;
float t2 = fetchDepth ( p + ivec2 ( 0 , 2 ) ) ;
float dl = abs ( ( 2.0 * l1 - l2 ) - c0 ) ;
float dr = abs ( ( 2.0 * r1 - r2 ) - c0 ) ;
float db = abs ( ( 2.0 * b1 - b2 ) - c0 ) ;
float dt = abs ( ( 2.0 * t1 - t2 ) - c0 ) ;
vec3 ce = getViewPosition ( uv , c0 ) . xyz ;
vec3 dpdx = ( dl < dr ) ? ce - getViewPosition ( ( uv - vec2 ( 1.0 / size . x , 0.0 ) ) , l1 ) . xyz
: - ce + getViewPosition ( ( uv + vec2 ( 1.0 / size . x , 0.0 ) ) , r1 ) . xyz ;
vec3 dpdy = ( db < dt ) ? ce - getViewPosition ( ( uv - vec2 ( 0.0 , 1.0 / size . y ) ) , b1 ) . xyz
: - ce + getViewPosition ( ( uv + vec2 ( 0.0 , 1.0 / size . y ) ) , t1 ) . xyz ;
return normalize ( cross ( dpdx , dpdy ) ) ;
}
vec3 getViewNormal ( const vec2 uv ) {
# if NORMAL _VECTOR _TYPE == 2
return normalize ( textureLod ( tNormal , uv , 0. ) . rgb ) ;
# elif NORMAL _VECTOR _TYPE == 1
return unpackRGBToNormal ( textureLod ( tNormal , uv , 0. ) . rgb ) ;
# else
return computeNormalFromDepth ( uv ) ;
# endif
}
void denoiseSample ( in vec3 center , in vec3 viewNormal , in vec3 viewPos , in vec2 sampleUv , inout vec3 denoised , inout float totalWeight ) {
vec4 sampleTexel = textureLod ( tDiffuse , sampleUv , 0.0 ) ;
float sampleDepth = getDepth ( sampleUv ) ;
vec3 sampleNormal = getViewNormal ( sampleUv ) ;
vec3 neighborColor = sampleTexel . rgb ;
vec3 viewPosSample = getViewPosition ( sampleUv , sampleDepth ) ;
float normalDiff = dot ( viewNormal , sampleNormal ) ;
float normalSimilarity = pow ( max ( normalDiff , 0. ) , normalPhi ) ;
float lumaDiff = abs ( getLuminance ( neighborColor ) - getLuminance ( center ) ) ;
float lumaSimilarity = max ( 1.0 - lumaDiff / lumaPhi , 0.0 ) ;
float depthDiff = abs ( dot ( viewPos - viewPosSample , viewNormal ) ) ;
float depthSimilarity = max ( 1. - depthDiff / depthPhi , 0. ) ;
float w = lumaSimilarity * depthSimilarity * normalSimilarity ;
denoised += w * neighborColor ;
totalWeight += w ;
}
void main ( ) {
float depth = getDepth ( vUv . xy ) ;
vec3 viewNormal = getViewNormal ( vUv ) ;
if ( depth == 1. || dot ( viewNormal , viewNormal ) == 0. ) {
discard ;
return ;
}
vec4 texel = textureLod ( tDiffuse , vUv , 0.0 ) ;
vec3 center = texel . rgb ;
vec3 viewPos = getViewPosition ( vUv , depth ) ;
vec2 noiseResolution = vec2 ( textureSize ( tNoise , 0 ) ) ;
vec2 noiseUv = vUv * resolution / noiseResolution ;
vec4 noiseTexel = textureLod ( tNoise , noiseUv , 0.0 ) ;
vec2 noiseVec = vec2 ( sin ( noiseTexel [ index % 4 ] * 2. * PI ) , cos ( noiseTexel [ index % 4 ] * 2. * PI ) ) ;
mat2 rotationMatrix = mat2 ( noiseVec . x , - noiseVec . y , noiseVec . x , noiseVec . y ) ;
float totalWeight = 1.0 ;
vec3 denoised = texel . rgb ;
for ( int i = 0 ; i < SAMPLES ; i ++ ) {
vec3 sampleDir = poissonDisk [ i ] ;
vec2 offset = rotationMatrix * ( sampleDir . xy * ( 1. + sampleDir . z * ( radius - 1. ) ) / resolution ) ;
vec2 sampleUv = vUv + offset ;
denoiseSample ( center , viewNormal , viewPos , sampleUv , denoised , totalWeight ) ;
}
if ( totalWeight > 0. ) {
denoised /= totalWeight ;
}
gl _FragColor = FRAGMENT _OUTPUT ;
2026-01-28 18:40:46 +08:00
} ` };function Up(s,e,t){const n=P2(s,e,t);let i="vec3[SAMPLES](";for(let r=0;r<s;r++){const o=n[r];i+= ` vec3 ( $ { o . x } , $ { o . y } , $ { o . z } ) $ { r < s - 1 ? "," : ")" } ` }return i}function P2(s,e,t){const n=[];for(let i=0;i<s;i++){const r=2*Math.PI*e*i/s,o=Math.pow(i/(s-1),t);n.push(new P(Math.cos(r),Math.sin(r),o))}return n}class R2{constructor(e=Math){this.grad3=[[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]],this.grad4=[[0,1,1,1],[0,1,1,-1],[0,1,-1,1],[0,1,-1,-1],[0,-1,1,1],[0,-1,1,-1],[0,-1,-1,1],[0,-1,-1,-1],[1,0,1,1],[1,0,1,-1],[1,0,-1,1],[1,0,-1,-1],[-1,0,1,1],[-1,0,1,-1],[-1,0,-1,1],[-1,0,-1,-1],[1,1,0,1],[1,1,0,-1],[1,-1,0,1],[1,-1,0,-1],[-1,1,0,1],[-1,1,0,-1],[-1,-1,0,1],[-1,-1,0,-1],[1,1,1,0],[1,1,-1,0],[1,-1,1,0],[1,-1,-1,0],[-1,1,1,0],[-1,1,-1,0],[-1,-1,1,0],[-1,-1,-1,0]],this.p=[];for(let t=0;t<256;t++)this.p[t]=Math.floor(e.random()*256);this.perm=[];for(let t=0;t<512;t++)this.perm[t]=this.p[t&255];this.simplex=[[0,1,2,3],[0,1,3,2],[0,0,0,0],[0,2,3,1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,2,3,0],[0,2,1,3],[0,0,0,0],[0,3,1,2],[0,3,2,1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,3,2,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,2,0,3],[0,0,0,0],[1,3,0,2],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,3,0,1],[2,3,1,0],[1,0,2,3],[1,0,3,2],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,0,3,1],[0,0,0,0],[2,1,3,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,0,1,3],[0,0,0,0],[0,0,0,0],[0,0,0,0],[3,0,1,2],[3,0,2,1],[0,0,0,0],[3,1,2,0],[2,1,0,3],[0,0,0,0],[0,0,0,0],[0,0,0,0],[3,1,0,2],[0,0,0,0],[3,2,0,1],[3,2,1,0]]}noise(e,t){let n,i,r;const o=.5*(Math.sqrt(3)-1),a=(e+t)*o,l=Math.floor(e+a),c=Math.floor(t+a),h=(3-Math.sqrt(3))/6,u=(l+c)*h,d=l-u,f=c-u,g=e-d,p=t-f;let x,m;g>p?(x=1,m=0):(x=0,m=1);const b=g-x+h,v=p-m+h,y=g-1+2*h,M=p-1+2*h,E=l&255,A=c&255,R=this.perm[E+this.perm[A]]%12,_=this.perm[E+x+this.perm[A+m]]%12,S=this.perm[E+1+this.perm[A+1]]%12;let D=.5-g*g-p*p;D<0?n=0:(D*=D,n=D*D*this._dot(this.grad3[R],g,p));let C=.5-b*b-v*v;C<0?i=0:(C*=C,i=C*C*this._dot(this.grad3[_],b,v));let B=.5-y*y-M*M;return B<0?r=0:(B*=B,r=B*B*this._dot(this.grad3[S],y,M)),70*(n+i+r)}noise3d(e,t,n){let i,r,o,a;const l=(e+t+n)*.3333333333333333,c=Math.floor(e+l),h=Math.floor(t+l),u=Math.floor(n+l),d=1/6,f=(c+h+u)*d,g=c-f,p=h-f,x=u-f,m=e-g,b=t-p,v=n-x;let y,M,E,A,R,_;m>=b?b>=v?(y=1,M=0,E=0,A=1,R=1,_=0):m>=v?(y=1,M=0,E=0,A=1,R=0,_=1):(y=0,M=0,E=1,A=1,R=0,_=1):b<v?(y=0,M=0,E=1,A=0,R=1,_=1):m<v?(y=0,M=1,E=0,A=0,R=1,_=1):(y=0,M=1,E=0,A=1,R=1,_=0);const S=m-y+d,D=b-M+d,C=v-E+d,B=m-A+2*d,w=b-R+2*d,F=v-_+2*d,W=m-1+3*d,j=b-1+3*d, $ =v-1+3*d,q=c&255,re=h&255,X=u&255,Y=this.perm[q+this.perm[re+this.perm[X]]]%12,ge=this.perm[q+y+this.perm[re+M+this.perm[X+E]]]%12,pe=this.perm[q+A+this.perm[re+R+this.perm[X+_]]]%12,de=this.perm[q+1+this.perm[re+1+this.perm[X+1]]]%12;let ie=.6-m*m-b*b-v*v;ie<0?i=0:(ie*=ie,i=ie*ie*this._dot3(this.grad3[Y],m,b,v));let he=.6-S*S-D*D-C*C;he<0?r=0:(he*=he,r=he*he*this._dot3(this.grad3[ge],S,D,C));let fe=.6-B*B-w*w-F*F;fe<0?o=0:(fe*=fe,o=fe*fe*this._dot3(this.grad3[pe],B,w,F));let ve=.6-W*W-j*j- $ * $ ;return ve<0?a=0:(ve*=ve,a=ve*ve*this._dot3(this.grad3[de],W,j, $ )),32*(i+r+o+a)}noise4d(e,t,n,i){const r=this.grad4,o=this.simplex,a=this.perm,l=(Math.sqrt(5)-1)/4,c=(5-Math.sqrt(5))/20;let h,u,d,f,g;const p=(e+t+n+i)*l,x=Math.floor(e+p),m=Math.floor(t+p),b=Math.floor(n+p),v=Math.floor(i+p),y=(x+m+b+v)*c,M=x-y,E=m-y,A=b-y,R=v-y,_=e-M,S=t-E,D=n-A,C=i-R,B=_>S?32:0,w=_>D?16:0,F=S>D?8:0,W=_>C?4:0,j=S>C?2:0, $ =D>C?1:0,q=B+w+F+W+j+ $ ,re=o[q][0]>=3?1:0,X=o[q][1]>=3?1:0,Y=o[q][2]>=3?1:0,ge=o[q][3]>=3?1:0,pe=o[q][0]>=2?1:0,de=o[q][1]>=2?1:0,ie=o[q][2]>=2?1:0,he=o[q][3]>=2?1:0,fe=o[q][0]>=1?1:0,ve=o[q][1]>=1?1:0,we=o[q][2]>=1?1:0,Be=o[q][3]>=1?1:0,Je=_-re+c,Ne=S-X+c,T=D-Y+c,I=C-ge+c,V=_-pe+2*c,O=S-de+2*c,U=D-ie+2*c,z=C-he+2*c,ee=_-fe+3*c,J=S-ve+3*c,G=D-we+3*c,N=C-Be+3*c,L=_-1+4*c,H=S-1+4*c,K=D-1+4*c,le=C-1+4*c,te=x&255,Ae=m&255,be=b&255,Re=v&255,De=a[te+a[Ae+a[be+a[Re]]]]%32,ue=a[te+re+a[Ae+X+a[be+Y+a[Re+ge]]]]%32,ye=a[te+pe+a[Ae+de+a[be+ie+a[Re+he]]]]%32,Ve=a[te+fe+
2026-01-22 11:29:51 +08:00
varying vec2 vUv ;
void main ( ) {
vUv = uv ;
gl _Position = projectionMatrix * modelViewMatrix * vec4 ( position , 1.0 ) ;
} ` ,fragmentShader: `
uniform sampler2D tDiffuse ;
uniform vec3 defaultColor ;
uniform float defaultOpacity ;
uniform float luminosityThreshold ;
uniform float smoothWidth ;
varying vec2 vUv ;
void main ( ) {
vec4 texel = texture2D ( tDiffuse , vUv ) ;
float v = luminance ( texel . xyz ) ;
vec4 outputColor = vec4 ( defaultColor . rgb , defaultOpacity ) ;
float alpha = smoothstep ( luminosityThreshold , luminosityThreshold + smoothWidth , v ) ;
gl _FragColor = mix ( outputColor , texel , alpha ) ;
2026-01-28 18:40:46 +08:00
} ` };class Sr extends vs{constructor(e,t=1,n,i){super(),this.strength=t,this.radius=n,this.threshold=i,this.resolution=e!==void 0?new ce(e.x,e.y):new ce(256,256),this.clearColor=new Ue(0,0,0),this.needsSwap=!1,this.renderTargetsHorizontal=[],this.renderTargetsVertical=[],this.nMips=5;let r=Math.round(this.resolution.x/2),o=Math.round(this.resolution.y/2);this.renderTargetBright=new pn(r,o,{type:Rn}),this.renderTargetBright.texture.name="UnrealBloomPass.bright",this.renderTargetBright.texture.generateMipmaps=!1;for(let h=0;h<this.nMips;h++){const u=new pn(r,o,{type:Rn});u.texture.name="UnrealBloomPass.h"+h,u.texture.generateMipmaps=!1,this.renderTargetsHorizontal.push(u);const d=new pn(r,o,{type:Rn});d.texture.name="UnrealBloomPass.v"+h,d.texture.generateMipmaps=!1,this.renderTargetsVertical.push(d),r=Math.round(r/2),o=Math.round(o/2)}const a=L2;this.highPassUniforms=oi.clone(a.uniforms),this.highPassUniforms.luminosityThreshold.value=i,this.highPassUniforms.smoothWidth.value=.01,this.materialHighPassFilter=new Ut({uniforms:this.highPassUniforms,vertexShader:a.vertexShader,fragmentShader:a.fragmentShader}),this.separableBlurMaterials=[];const l=[6,10,14,18,22];r=Math.round(this.resolution.x/2),o=Math.round(this.resolution.y/2);for(let h=0;h<this.nMips;h++)this.separableBlurMaterials.push(this._getSeparableBlurMaterial(l[h])),this.separableBlurMaterials[h].uniforms.invSize.value=new ce(1/r,1/o),r=Math.round(r/2),o=Math.round(o/2);this.compositeMaterial=this._getCompositeMaterial(this.nMips),this.compositeMaterial.uniforms.blurTexture1.value=this.renderTargetsVertical[0].texture,this.compositeMaterial.uniforms.blurTexture2.value=this.renderTargetsVertical[1].texture,this.compositeMaterial.uniforms.blurTexture3.value=this.renderTargetsVertical[2].texture,this.compositeMaterial.uniforms.blurTexture4.value=this.renderTargetsVertical[3].texture,this.compositeMaterial.uniforms.blurTexture5.value=this.renderTargetsVertical[4].texture,this.compositeMaterial.uniforms.bloomStrength.value=t,this.compositeMaterial.uniforms.bloomRadius.value=.1;const c=[1,.8,.6,.4,.2];this.compositeMaterial.uniforms.bloomFactors.value=c,this.bloomTintColors=[new P(1,1,1),new P(1,1,1),new P(1,1,1),new P(1,1,1),new P(1,1,1)],this.compositeMaterial.uniforms.bloomTintColors.value=this.bloomTintColors,this.copyUniforms=oi.clone(xs.uniforms),this.blendMaterial=new Ut({uniforms:this.copyUniforms,vertexShader:xs.vertexShader,fragmentShader:xs.fragmentShader,blending:Hl,depthTest:!1,depthWrite:!1,transparent:!0}),this._oldClearColor=new Ue,this._oldClearAlpha=1,this._basic=new Xt,this._fsQuad=new Wa(null)}dispose(){for(let e=0;e<this.renderTargetsHorizontal.length;e++)this.renderTargetsHorizontal[e].dispose();for(let e=0;e<this.renderTargetsVertical.length;e++)this.renderTargetsVertical[e].dispose();this.renderTargetBright.dispose();for(let e=0;e<this.separableBlurMaterials.length;e++)this.separableBlurMaterials[e].dispose();this.compositeMaterial.dispose(),this.blendMaterial.dispose(),this._basic.dispose(),this._fsQuad.dispose()}setSize(e,t){let n=Math.round(e/2),i=Math.round(t/2);this.renderTargetBright.setSize(n,i);for(let r=0;r<this.nMips;r++)this.renderTargetsHorizontal[r].setSize(n,i),this.renderTargetsVertical[r].setSize(n,i),this.separableBlurMaterials[r].uniforms.invSize.value=new ce(1/n,1/i),n=Math.round(n/2),i=Math.round(i/2)}render(e,t,n,i,r){e.getClearColor(this._oldClearColor),this._oldClearAlpha=e.getClearAlpha();const o=e.autoClear;e.autoClear=!1,e.setClearColor(this.clearColor,0),r&&e.state.buffers.stencil.setTest(!1),this.renderToScreen&&(this._fsQuad.material=this._basic,this._basic.map=n.texture,e.setRenderTarget(null),e.clear(),this._fsQuad.render(e)),this.highPassUniforms.tDiffuse.value=n.texture,this.highPassUniforms.luminosityThreshold.value=this.threshold,this._fsQuad.material=this.materialHighPassFilter,e.setRenderTarget(this.renderTargetBright),e.clear(),this._fsQuad.render(e);let a=this.renderTargetBright;for(let l=0;l<this.nMips;l++)this._fsQuad.material=this.separableBlurMaterials[l],this.separableBlurMaterials[l].uniforms.colorT
2026-01-22 11:29:51 +08:00
void main ( ) {
vUv = uv ;
gl _Position = projectionMatrix * modelViewMatrix * vec4 ( position , 1.0 ) ;
} ` ,fragmentShader: ` # include < common >
varying vec2 vUv ;
uniform sampler2D colorTexture ;
uniform vec2 invSize ;
uniform vec2 direction ;
uniform float gaussianCoefficients [ KERNEL _RADIUS ] ;
void main ( ) {
float weightSum = gaussianCoefficients [ 0 ] ;
vec3 diffuseSum = texture2D ( colorTexture , vUv ) . rgb * weightSum ;
for ( int i = 1 ; i < KERNEL _RADIUS ; i ++ ) {
float x = float ( i ) ;
float w = gaussianCoefficients [ i ] ;
vec2 uvOffset = direction * invSize * x ;
vec3 sample1 = texture2D ( colorTexture , vUv + uvOffset ) . rgb ;
vec3 sample2 = texture2D ( colorTexture , vUv - uvOffset ) . rgb ;
diffuseSum += ( sample1 + sample2 ) * w ;
}
gl _FragColor = vec4 ( diffuseSum , 1.0 ) ;
2026-01-28 18:40:46 +08:00
} ` })}_getCompositeMaterial(e){return new Ut({defines:{NUM_MIPS:e},uniforms:{blurTexture1:{value:null},blurTexture2:{value:null},blurTexture3:{value:null},blurTexture4:{value:null},blurTexture5:{value:null},bloomStrength:{value:1},bloomFactors:{value:null},bloomTintColors:{value:null},bloomRadius:{value:0}},vertexShader: ` varying vec2 vUv ;
2026-01-22 11:29:51 +08:00
void main ( ) {
vUv = uv ;
gl _Position = projectionMatrix * modelViewMatrix * vec4 ( position , 1.0 ) ;
} ` ,fragmentShader: ` varying vec2 vUv ;
uniform sampler2D blurTexture1 ;
uniform sampler2D blurTexture2 ;
uniform sampler2D blurTexture3 ;
uniform sampler2D blurTexture4 ;
uniform sampler2D blurTexture5 ;
uniform float bloomStrength ;
uniform float bloomRadius ;
uniform float bloomFactors [ NUM _MIPS ] ;
uniform vec3 bloomTintColors [ NUM _MIPS ] ;
float lerpBloomFactor ( const in float factor ) {
float mirrorFactor = 1.2 - factor ;
return mix ( factor , mirrorFactor , bloomRadius ) ;
}
void main ( ) {
gl _FragColor = bloomStrength * ( lerpBloomFactor ( bloomFactors [ 0 ] ) * vec4 ( bloomTintColors [ 0 ] , 1.0 ) * texture2D ( blurTexture1 , vUv ) +
lerpBloomFactor ( bloomFactors [ 1 ] ) * vec4 ( bloomTintColors [ 1 ] , 1.0 ) * texture2D ( blurTexture2 , vUv ) +
lerpBloomFactor ( bloomFactors [ 2 ] ) * vec4 ( bloomTintColors [ 2 ] , 1.0 ) * texture2D ( blurTexture3 , vUv ) +
lerpBloomFactor ( bloomFactors [ 3 ] ) * vec4 ( bloomTintColors [ 3 ] , 1.0 ) * texture2D ( blurTexture4 , vUv ) +
lerpBloomFactor ( bloomFactors [ 4 ] ) * vec4 ( bloomTintColors [ 4 ] , 1.0 ) * texture2D ( blurTexture5 , vUv ) ) ;
2026-01-28 18:40:46 +08:00
} ` })}}Sr.BlurDirectionX=new ce(1,0),Sr.BlurDirectionY=new ce(0,1);const Ya={name:"OutputShader",uniforms:{tDiffuse:{value:null},toneMappingExposure:{value:1}},vertexShader: `
2026-01-22 11:29:51 +08:00
precision highp float ;
uniform mat4 modelViewMatrix ;
uniform mat4 projectionMatrix ;
attribute vec3 position ;
attribute vec2 uv ;
varying vec2 vUv ;
void main ( ) {
vUv = uv ;
gl _Position = projectionMatrix * modelViewMatrix * vec4 ( position , 1.0 ) ;
} ` ,fragmentShader: `
precision highp float ;
uniform sampler2D tDiffuse ;
# include < tonemapping _pars _fragment >
# include < colorspace _pars _fragment >
varying vec2 vUv ;
void main ( ) {
gl _FragColor = texture2D ( tDiffuse , vUv ) ;
// tone mapping
# ifdef LINEAR _TONE _MAPPING
gl _FragColor . rgb = LinearToneMapping ( gl _FragColor . rgb ) ;
# elif defined ( REINHARD _TONE _MAPPING )
gl _FragColor . rgb = ReinhardToneMapping ( gl _FragColor . rgb ) ;
# elif defined ( CINEON _TONE _MAPPING )
gl _FragColor . rgb = CineonToneMapping ( gl _FragColor . rgb ) ;
# elif defined ( ACES _FILMIC _TONE _MAPPING )
gl _FragColor . rgb = ACESFilmicToneMapping ( gl _FragColor . rgb ) ;
# elif defined ( AGX _TONE _MAPPING )
gl _FragColor . rgb = AgXToneMapping ( gl _FragColor . rgb ) ;
# elif defined ( NEUTRAL _TONE _MAPPING )
gl _FragColor . rgb = NeutralToneMapping ( gl _FragColor . rgb ) ;
# elif defined ( CUSTOM _TONE _MAPPING )
gl _FragColor . rgb = CustomToneMapping ( gl _FragColor . rgb ) ;
# endif
// color space
# ifdef SRGB _TRANSFER
gl _FragColor = sRGBTransferOETF ( gl _FragColor ) ;
# endif
2026-01-28 18:40:46 +08:00
} ` };class D2 extends vs{constructor(){super(),this.uniforms=oi.clone(Ya.uniforms),this.material=new dv({name:Ya.name,uniforms:this.uniforms,vertexShader:Ya.vertexShader,fragmentShader:Ya.fragmentShader}),this._fsQuad=new Wa(this.material),this._outputColorSpace=null,this._toneMapping=null}render(e,t,n){this.uniforms.tDiffuse.value=n.texture,this.uniforms.toneMappingExposure.value=e.toneMappingExposure,(this._outputColorSpace!==e.outputColorSpace||this._toneMapping!==e.toneMapping)&&(this._outputColorSpace=e.outputColorSpace,this._toneMapping=e.toneMapping,this.material.defines={},it.getTransfer(this._outputColorSpace)===lt&&(this.material.defines.SRGB_TRANSFER=""),this._toneMapping===ud?this.material.defines.LINEAR_TONE_MAPPING="":this._toneMapping===dd?this.material.defines.REINHARD_TONE_MAPPING="":this._toneMapping===fd?this.material.defines.CINEON_TONE_MAPPING="":this._toneMapping===Ql?this.material.defines.ACES_FILMIC_TONE_MAPPING="":this._toneMapping===md?this.material.defines.AGX_TONE_MAPPING="":this._toneMapping===gd?this.material.defines.NEUTRAL_TONE_MAPPING="":this._toneMapping===pd&&(this.material.defines.CUSTOM_TONE_MAPPING=""),this.material.needsUpdate=!0),this.renderToScreen===!0?(e.setRenderTarget(null),this._fsQuad.render(e)):(e.setRenderTarget(t),this.clear&&e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil),this._fsQuad.render(e))}dispose(){this.material.dispose(),this._fsQuad.dispose()}}const I2={name:"FXAAShader",uniforms:{tDiffuse:{value:null},resolution:{value:new ce(1/1024,1/512)}},vertexShader: `
2026-01-22 11:29:51 +08:00
varying vec2 vUv ;
void main ( ) {
vUv = uv ;
gl _Position = projectionMatrix * modelViewMatrix * vec4 ( position , 1.0 ) ;
} ` ,fragmentShader: `
uniform sampler2D tDiffuse ;
uniform vec2 resolution ;
varying vec2 vUv ;
# define EDGE _STEP _COUNT 6
# define EDGE _GUESS 8.0
# define EDGE _STEPS 1.0 , 1.5 , 2.0 , 2.0 , 2.0 , 4.0
const float edgeSteps [ EDGE _STEP _COUNT ] = float [ EDGE _STEP _COUNT ] ( EDGE _STEPS ) ;
float _ContrastThreshold = 0.0312 ;
float _RelativeThreshold = 0.063 ;
float _SubpixelBlending = 1.0 ;
vec4 Sample ( sampler2D tex2D , vec2 uv ) {
return texture ( tex2D , uv ) ;
}
float SampleLuminance ( sampler2D tex2D , vec2 uv ) {
return dot ( Sample ( tex2D , uv ) . rgb , vec3 ( 0.3 , 0.59 , 0.11 ) ) ;
}
float SampleLuminance ( sampler2D tex2D , vec2 texSize , vec2 uv , float uOffset , float vOffset ) {
uv += texSize * vec2 ( uOffset , vOffset ) ;
return SampleLuminance ( tex2D , uv ) ;
}
struct LuminanceData {
float m , n , e , s , w ;
float ne , nw , se , sw ;
float highest , lowest , contrast ;
} ;
LuminanceData SampleLuminanceNeighborhood ( sampler2D tex2D , vec2 texSize , vec2 uv ) {
LuminanceData l ;
l . m = SampleLuminance ( tex2D , uv ) ;
l . n = SampleLuminance ( tex2D , texSize , uv , 0.0 , 1.0 ) ;
l . e = SampleLuminance ( tex2D , texSize , uv , 1.0 , 0.0 ) ;
l . s = SampleLuminance ( tex2D , texSize , uv , 0.0 , - 1.0 ) ;
l . w = SampleLuminance ( tex2D , texSize , uv , - 1.0 , 0.0 ) ;
l . ne = SampleLuminance ( tex2D , texSize , uv , 1.0 , 1.0 ) ;
l . nw = SampleLuminance ( tex2D , texSize , uv , - 1.0 , 1.0 ) ;
l . se = SampleLuminance ( tex2D , texSize , uv , 1.0 , - 1.0 ) ;
l . sw = SampleLuminance ( tex2D , texSize , uv , - 1.0 , - 1.0 ) ;
l . highest = max ( max ( max ( max ( l . n , l . e ) , l . s ) , l . w ) , l . m ) ;
l . lowest = min ( min ( min ( min ( l . n , l . e ) , l . s ) , l . w ) , l . m ) ;
l . contrast = l . highest - l . lowest ;
return l ;
}
bool ShouldSkipPixel ( LuminanceData l ) {
float threshold = max ( _ContrastThreshold , _RelativeThreshold * l . highest ) ;
return l . contrast < threshold ;
}
float DeterminePixelBlendFactor ( LuminanceData l ) {
float f = 2.0 * ( l . n + l . e + l . s + l . w ) ;
f += l . ne + l . nw + l . se + l . sw ;
f *= 1.0 / 12.0 ;
f = abs ( f - l . m ) ;
f = clamp ( f / l . contrast , 0.0 , 1.0 ) ;
float blendFactor = smoothstep ( 0.0 , 1.0 , f ) ;
return blendFactor * blendFactor * _SubpixelBlending ;
}
struct EdgeData {
bool isHorizontal ;
float pixelStep ;
float oppositeLuminance , gradient ;
} ;
EdgeData DetermineEdge ( vec2 texSize , LuminanceData l ) {
EdgeData e ;
float horizontal =
abs ( l . n + l . s - 2.0 * l . m ) * 2.0 +
abs ( l . ne + l . se - 2.0 * l . e ) +
abs ( l . nw + l . sw - 2.0 * l . w ) ;
float vertical =
abs ( l . e + l . w - 2.0 * l . m ) * 2.0 +
abs ( l . ne + l . nw - 2.0 * l . n ) +
abs ( l . se + l . sw - 2.0 * l . s ) ;
e . isHorizontal = horizontal >= vertical ;
float pLuminance = e . isHorizontal ? l . n : l . e ;
float nLuminance = e . isHorizontal ? l . s : l . w ;
float pGradient = abs ( pLuminance - l . m ) ;
float nGradient = abs ( nLuminance - l . m ) ;
e . pixelStep = e . isHorizontal ? texSize . y : texSize . x ;
if ( pGradient < nGradient ) {
e . pixelStep = - e . pixelStep ;
e . oppositeLuminance = nLuminance ;
e . gradient = nGradient ;
} else {
e . oppositeLuminance = pLuminance ;
e . gradient = pGradient ;
}
return e ;
}
float DetermineEdgeBlendFactor ( sampler2D tex2D , vec2 texSize , LuminanceData l , EdgeData e , vec2 uv ) {
vec2 uvEdge = uv ;
vec2 edgeStep ;
if ( e . isHorizontal ) {
uvEdge . y += e . pixelStep * 0.5 ;
edgeStep = vec2 ( texSize . x , 0.0 ) ;
} else {
uvEdge . x += e . pixelStep * 0.5 ;
edgeStep = vec2 ( 0.0 , texSize . y ) ;
}
float edgeLuminance = ( l . m + e . oppositeLuminance ) * 0.5 ;
float gradientThreshold = e . gradient * 0.25 ;
vec2 puv = uvEdge + edgeStep * edgeSteps [ 0 ] ;
float pLuminanceDelta = SampleLuminance ( tex2D , puv ) - edgeLuminance ;
bool pAtEnd = abs ( pLuminanceDelta ) >= gradientThreshold ;
for ( int i = 1 ; i < EDGE _STEP _COUNT && ! pAtEnd ; i ++ ) {
puv += edgeStep * edgeSteps [ i ] ;
pLuminanceDelta = SampleLuminance ( tex2D , puv ) - edgeLuminance ;
pAtEnd = abs ( pLuminanceDelta ) >= gradientThreshold ;
}
if ( ! pAtEnd ) {
puv += edgeStep * EDGE _GUESS ;
}
vec2 nuv = uvEdge - edgeStep * edgeSteps [ 0 ] ;
float nLuminanceDelta = SampleLuminance ( tex2D , nuv ) - edgeLuminance ;
bool nAtEnd = abs ( nLuminanceDelta ) >= gradientThreshold ;
for ( int i = 1 ; i < EDGE _STEP _COUNT && ! nAtEnd ; i ++ ) {
nuv -= edgeStep * edgeSteps [ i ] ;
nLuminanceDelta = SampleLuminance ( tex2D , nuv ) - edgeLuminance ;
nAtEnd = abs ( nLuminanceDelta ) >= gradientThreshold ;
}
if ( ! nAtEnd ) {
nuv -= edgeStep * EDGE _GUESS ;
}
float pDistance , nDistance ;
if ( e . isHorizontal ) {
pDistance = puv . x - uv . x ;
nDistance = uv . x - nuv . x ;
} else {
pDistance = puv . y - uv . y ;
nDistance = uv . y - nuv . y ;
}
float shortestDistance ;
bool deltaSign ;
if ( pDistance <= nDistance ) {
shortestDistance = pDistance ;
deltaSign = pLuminanceDelta >= 0.0 ;
} else {
shortestDistance = nDistance ;
deltaSign = nLuminanceDelta >= 0.0 ;
}
if ( deltaSign == ( l . m - edgeLuminance >= 0.0 ) ) {
return 0.0 ;
}
return 0.5 - shortestDistance / ( pDistance + nDistance ) ;
}
vec4 ApplyFXAA ( sampler2D tex2D , vec2 texSize , vec2 uv ) {
LuminanceData luminance = SampleLuminanceNeighborhood ( tex2D , texSize , uv ) ;
if ( ShouldSkipPixel ( luminance ) ) {
return Sample ( tex2D , uv ) ;
}
float pixelBlend = DeterminePixelBlendFactor ( luminance ) ;
EdgeData edge = DetermineEdge ( texSize , luminance ) ;
float edgeBlend = DetermineEdgeBlendFactor ( tex2D , texSize , luminance , edge , uv ) ;
float finalBlend = max ( pixelBlend , edgeBlend ) ;
if ( edge . isHorizontal ) {
uv . y += edge . pixelStep * finalBlend ;
} else {
uv . x += edge . pixelStep * finalBlend ;
}
return Sample ( tex2D , uv ) ;
}
void main ( ) {
gl _FragColor = ApplyFXAA ( tDiffuse , resolution . xy , vUv ) ;
2026-01-28 17:19:36 +08:00
} ` },B2={uniforms:{tDiffuse:{value:null},saturation:{value:1.2},contrast:{value:1.2}},vertexShader: `
2026-01-22 11:29:51 +08:00
varying vec2 vUv ;
void main ( ) {
vUv = uv ;
gl _Position = projectionMatrix * modelViewMatrix * vec4 ( position , 1.0 ) ;
}
` ,fragmentShader: `
uniform sampler2D tDiffuse ;
uniform float saturation ;
uniform float contrast ;
varying vec2 vUv ;
void main ( ) {
vec4 color = texture2D ( tDiffuse , vUv ) ;
// 转换为灰度值用于饱和度调整
float gray = dot ( color . rgb , vec3 ( 0.299 , 0.587 , 0.114 ) ) ;
// 混合原始颜色和灰度值来调整饱和度
color . rgb = mix ( vec3 ( gray ) , color . rgb , saturation ) ;
// 调整对比度
color . rgb = ( color . rgb - 0.5 ) * contrast + 0.5 ;
gl _FragColor = color ;
}
2026-01-28 18:40:46 +08:00
` };class N2{engine;composer;saturationPass;constructor(e){this.engine=e}resize(e,t){if(e===void 0||t===void 0){const r=this.engine.deviceModule.getContainerSize();e=e??r.width,t=t??r.height}if(!e||!t||!this.composer)return;const n=this.engine.renderer?.getPixelRatio?.()??window.devicePixelRatio??1;this.composer.setPixelRatio(n),this.composer.setSize(e,t);const i=this.composer.passes.find(r=>r instanceof Xa&&r.material.uniforms.resolution);i&&(i.material.uniforms.resolution.value.x=1/(e*n),i.material.uniforms.resolution.value.y=1/(t*n))}init(){const{width:e,height:t}=this.engine.deviceModule.getContainerSize(),n=this.engine.scene,i=this.engine.camera,r=this.engine.renderer,o=this.engine.renderer?.getPixelRatio?.()??window.devicePixelRatio??1,a=new pn(e,t,{minFilter: $ t,magFilter: $ t,format:fn,samples:4});this.composer=new E2(r,a),this.composer.setPixelRatio(o),this.composer.setSize(e,t);const l=new T2(n,i);this.composer.addPass(l);const c=new bn(n,i,e,t);c.output=bn.OUTPUT.Default,c.blendIntensity=.5,c.updateGtaoMaterial&&c.updateGtaoMaterial({radius:1,distanceExponent:1,thickness:1,scale:1,distanceFallOff:1,screenSpaceRadius:!0}),new Sr(new ce(e,t),.1,.1,.5),this.saturationPass=new Xa(B2),this.saturationPass.uniforms.saturation.value=1.3,this.saturationPass.uniforms.contrast.value=1.1,this.composer.addPass(this.saturationPass);const h=new D2;this.composer.addPass(h);const u=new Xa(I2);u.material.uniforms.resolution.value.x=1/(e*o),u.material.uniforms.resolution.value.y=1/(t*o),this.composer.addPass(u)}}var Ka=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Op(s){return s&&s.__esModule&&Object.prototype.hasOwnProperty.call(s,"default")?s.default:s}function $ a(s){throw new Error('Could not dynamically require "'+s+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var kp={exports:{}},Fp;function U2(){return Fp||(Fp=1,(function(s,e){(function(t){s.exports=t()})(function(){return(function t(n,i,r){function o(c,h){if(!i[c]){if(!n[c]){var u=typeof $ a=="function"&& $ a;if(!h&&u)return u(c,!0);if(a)return a(c,!0);var d=new Error("Cannot find module '"+c+"'");throw d.code="MODULE_NOT_FOUND",d}var f=i[c]={exports:{}};n[c][0].call(f.exports,function(g){var p=n[c][1][g];return o(p||g)},f,f.exports,t,n,i,r)}return i[c].exports}for(var a=typeof $ a=="function"&& $ a,l=0;l<r.length;l++)o(r[l]);return o})({1:[function(t,n,i){var r=t("./utils"),o=t("./support"),a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";i.encode=function(l){for(var c,h,u,d,f,g,p,x=[],m=0,b=l.length,v=b,y=r.getTypeOf(l)!=="string";m<l.length;)v=b-m,u=y?(c=l[m++],h=m<b?l[m++]:0,m<b?l[m++]:0):(c=l.charCodeAt(m++),h=m<b?l.charCodeAt(m++):0,m<b?l.charCodeAt(m++):0),d=c>>2,f=(3&c)<<4|h>>4,g=1<v?(15&h)<<2|u>>6:64,p=2<v?63&u:64,x.push(a.charAt(d)+a.charAt(f)+a.charAt(g)+a.charAt(p));return x.join("")},i.decode=function(l){var c,h,u,d,f,g,p=0,x=0,m="data:";if(l.substr(0,m.length)===m)throw new Error("Invalid base64 input, it looks like a data url.");var b,v=3*(l=l.replace(/[^A-Za-z0-9+/=]/g,"")).length/4;if(l.charAt(l.length-1)===a.charAt(64)&&v--,l.charAt(l.length-2)===a.charAt(64)&&v--,v%1!=0)throw new Error("Invalid base64 input, bad content length.");for(b=o.uint8array?new Uint8Array(0|v):new Array(0|v);p<l.length;)c=a.indexOf(l.charAt(p++))<<2|(d=a.indexOf(l.charAt(p++)))>>4,h=(15&d)<<4|(f=a.indexOf(l.charAt(p++)))>>2,u=(3&f)<<6|(g=a.indexOf(l.charAt(p++))),b[x++]=c,f!==64&&(b[x++]=h),g!==64&&(b[x++]=u);return b}},{"./support":30,"./utils":32}],2:[function(t,n,i){var r=t("./external"),o=t("./stream/DataWorker"),a=t("./stream/Crc32Probe"),l=t("./stream/DataLengthProbe");function c(h,u,d,f,g){this.compressedSize=h,this.uncompressedSize=u,this.crc32=d,this.compression=f,this.compressedContent=g}c.prototype={getContentWorker:function(){var h=new o(r.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new l("data_length")),u=this;return h.on("end",f
\ 0 ` ,pe+=r(X,2),pe+=E.magic,pe+=r(v,2),pe+=r(y,2),pe+=r(re.crc32,4),pe+=r(re.compressedSize,4),pe+=r(re.uncompressedSize,4),pe+=r(R.length,2),pe+=r(F.length,2),{fileRecord:u.LOCAL_FILE_HEADER+pe+R+F,dirRecord:u.CENTRAL_FILE_HEADER+r(ge,2)+pe+r(D.length,2)+" \0 \0 \0 \0 "+r(Y,4)+r(x,4)+R+F+D}}var a=t("../utils"),l=t("../stream/GenericWorker"),c=t("../utf8"),h=t("../crc32"),u=t("../signature");function d(f,g,p,x){l.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=g,this.zipPlatform=p,this.encodeFileName=x,this.streamFiles=f,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}a.inherits(d,l),d.prototype.push=function(f){var g=f.meta.percent||0,p=this.entriesCount,x=this._sources.length;this.accumulate?this.contentBuffer.push(f):(this.bytesWritten+=f.data.length,l.prototype.push.call(this,{data:f.data,meta:{currentFile:this.currentFile,percent:p?(g+100*(p-x-1))/p:100}}))},d.prototype.openedSource=function(f){this.currentSourceOffset=this.bytesWritten,this.currentFile=f.file.name;var g=this.streamFiles&&!f.file.dir;if(g){var p=o(f,g,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:p.fileRecord,meta:{percent:0}})}else this.accumulate=!0},d.prototype.closedSource=function(f){this.accumulate=!1;var g=this.streamFiles&&!f.file.dir,p=o(f,g,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(p.dirRecord),g)this.push({data:(function(x){return u.DATA_DESCRIPTOR+r(x.crc32,4)+r(x.compressedSize,4)+r(x.uncompressedSize,4)})(f),meta:{percent:100}});else for(this.push({data:p.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},d.prototype.flush=function(){for(var f=this.bytesWritten,g=0;g<this.dirRecords.length;g++)this.push({data:this.dirRecords[g],meta:{percent:100}});var p=this.bytesWritten-f,x=(function(m,b,v,y,M){var E=a.transformTo("string",M(y));return u.CENTRAL_DIRECTORY_END+" \0 \0 \0 \0 "+r(m,2)+r(m,2)+r(b,4)+r(v,4)+r(E.length,2)+E})(this.dirRecords.length,p,f,this.zipComment,this.encodeFileName);this.push({data:x,meta:{percent:100}})},d.prototype.prepareNextSource=function(){this.previous=this._sources.shift(),this.openedSource(this.previous.streamInfo),this.isPaused?this.previous.pause():this.previous.resume()},d.prototype.registerPrevious=function(f){this._sources.push(f);var g=this;return f.on("data",function(p){g.processChunk(p)}),f.on("end",function(){g.closedSource(g.previous.streamInfo),g._sources.length?g.prepareNextSource():g.end()}),f.on("error",function(p){g.error(p)}),this},d.prototype.resume=function(){return!!l.prototype.resume.call(this)&&(!this.previous&&this._sources.length?(this.prepareNextSource(),!0):this.previous||this._sources.length||this.generatedError?void 0:(this.end(),!0))},d.prototype.error=function(f){var g=this._sources;if(!l.prototype.error.call(this,f))return!1;for(var p=0;p<g.length;p++)try{g[p].error(f)}catch{}return!0},d.prototype.lock=function(){l.prototype.lock.call(this);for(var f=this._sources,g=0;g<f.length;g++)f[g].lock()},n.exports=d},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(t,n,i){var r=t("../compressions"),o=t("./ZipFileWorker");i.generateWorker=function(a,l,c){var h=new o(l.streamFiles,c,l.platform,l.encodeFileName),u=0;try{a.forEach(function(d,f){u++;var g=(function(b,v){var y=b||v,M=r[y];if(!M)throw new Error(y+" is not a valid compression method !");return M})(f.options.compression,l.compression),p=f.options.compressionOptions||l.compressionOptions||{},x=f.dir,m=f.date;f._compressWorker(g,p).withStreamInfo("file",{name:d,dir:x,date:m,comment:f.comment||"",unixPermissions:f.unixPermissions,dosPermissions:f.dosPermissions}).pipe(h)}),h.entriesCount=u}catch(d){h.error(d)}return h}},{"../compressions":3,"./ZipFileWorker":8}],10:[function(t,n,i){function r(){if(!(this instanceof r))return new r;if(arguments.length)throw new Error("The constructor with parameters has been removed in JSZip 3.0, pl
` ).forEach(function(r){i=r.indexOf(":"),t=r.substring(0,i).trim().toLowerCase(),n=r.substring(i+1).trim(),!(!t||e[t]&&FM[t])&&(t==="set-cookie"?e[t]?e[t].push(n):e[t]=[n]:e[t]=e[t]?e[t]+", "+n:n)}),e},om=Symbol("internals");function Po(s){return s&&String(s).trim().toLowerCase()}function il(s){return s===!1||s==null?s:se.isArray(s)?s.map(il):String(s)}function HM(s){const e=Object.create(null),t=/([^ \s ,;=]+) \s *(?:= \s *([^,;]+))?/g;let n;for(;n=t.exec(s);)e[n[1]]=n[2];return e}const VM=s=>/^[-_a-zA-Z0-9^ ` | ~ , ! # $ % & ' * + . ] + $ / . test ( s . trim ( ) ) ; function eu ( s , e , t , n , i ) { if ( se . isFunction ( n ) ) return n . call ( this , e , t ) ; if ( i && ( e = t ) , ! ! se . isString ( e ) ) { if ( se . isString ( n ) ) return e . indexOf ( n ) !== - 1 ; if ( se . isRegExp ( n ) ) return n . test ( e ) } } function GM ( s ) { return s . trim ( ) . toLowerCase ( ) . replace ( /([a-z\d])(\w*)/g , ( e , t , n ) => t . toUpperCase ( ) + n ) } function WM ( s , e ) { const t = se . toCamelCase ( " " + e ) ; [ "get" , "set" , "has" ] . forEach ( n => { Object . defineProperty ( s , n + t , { value : function ( i , r , o ) { return this [ n ] . call ( this , e , i , r , o ) } , configurable : ! 0 } ) } ) } let _n = class { constructor ( s ) { s && this . set ( s ) } set ( s , e , t ) { const n = this ; function i ( o , a , l ) { const c = Po ( a ) ; if ( ! c ) throw new Error ( "header name must be a non-empty string" ) ; const h = se . findKey ( n , c ) ; ( ! h || n [ h ] === void 0 || l === ! 0 || l === void 0 && n [ h ] !== ! 1 ) && ( n [ h || a ] = il ( o ) ) } const r = ( o , a ) => se . forEach ( o , ( l , c ) => i ( l , c , a ) ) ; if ( se . isPlainObject ( s ) || s instanceof this . constructor ) r ( s , e ) ; else if ( se . isString ( s ) && ( s = s . trim ( ) ) && ! VM ( s ) ) r ( zM ( s ) , e ) ; else if ( se . isObject ( s ) && se . isIterable ( s ) ) { let o = { } , a , l ; for ( const c of s ) { if ( ! se . isArray ( c ) ) throw TypeError ( "Object iterator must return a key-value pair" ) ; o [ l = c [ 0 ] ] = ( a = o [ l ] ) ? se . isArray ( a ) ? [ ... a , c [ 1 ] ] : [ a , c [ 1 ] ] : c [ 1 ] } r ( o , e ) } else s != null && i ( e , s , t ) ; return this } get ( s , e ) { if ( s = Po ( s ) , s ) { const t = se . findKey ( this , s ) ; if ( t ) { const n = this [ t ] ; if ( ! e ) return n ; if ( e === ! 0 ) return HM ( n ) ; if ( se . isFunction ( e ) ) return e . call ( this , n , t ) ; if ( se . isRegExp ( e ) ) return e . exec ( n ) ; throw new TypeError ( "parser must be boolean|regexp|function" ) } } } has ( s , e ) { if ( s = Po ( s ) , s ) { const t = se . findKey ( this , s ) ; return ! ! ( t && this [ t ] !== void 0 && ( ! e || eu ( this , this [ t ] , t , e ) ) ) } return ! 1 } delete ( s , e ) { const t = this ; let n = ! 1 ; function i ( r ) { if ( r = Po ( r ) , r ) { const o = se . findKey ( t , r ) ; o && ( ! e || eu ( t , t [ o ] , o , e ) ) && ( delete t [ o ] , n = ! 0 ) } } return se . isArray ( s ) ? s . forEach ( i ) : i ( s ) , n } clear ( s ) { const e = Object . keys ( this ) ; let t = e . length , n = ! 1 ; for ( ; t -- ; ) { const i = e [ t ] ; ( ! s || eu ( this , this [ i ] , i , s , ! 0 ) ) && ( delete this [ i ] , n = ! 0 ) } return n } normalize ( s ) { const e = this , t = { } ; return se . forEach ( this , ( n , i ) => { const r = se . findKey ( t , i ) ; if ( r ) { e [ r ] = il ( n ) , delete e [ i ] ; return } const o = s ? GM ( i ) : String ( i ) . trim ( ) ; o !== i && delete e [ i ] , e [ o ] = il ( n ) , t [ o ] = ! 0 } ) , this } concat ( ... s ) { return this . constructor . concat ( this , ... s ) } toJSON ( s ) { const e = Object . create ( null ) ; return se . forEach ( this , ( t , n ) => { t != null && t !== ! 1 && ( e [ n ] = s && se . isArray ( t ) ? t . join ( ", " ) : t ) } ) , e } [ Symbol . iterator ] ( ) { return Object . entries ( this . toJSON ( ) ) [ Symbol . iterator ] ( ) } toString ( ) { return Object . entries ( this . toJSON ( ) ) . map ( ( [ s , e ] ) => s + ": " + e ) . join ( `
` )}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(s){return s instanceof this?s:new this(s)}static concat(s,...e){const t=new this(s);return e.forEach(n=>t.set(n)),t}static accessor(s){const e=(this[om]=this[om]={accessors:{}}).accessors,t=this.prototype;function n(i){const r=Po(i);e[r]||(WM(t,i),e[r]=!0)}return se.isArray(s)?s.forEach(n):n(s),this}};_n.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),se.reduceDescriptors(_n.prototype,({value:s},e)=>{let t=e[0].toUpperCase()+e.slice(1);return{get:()=>s,set(n){this[t]=n}}}),se.freezeMethods(_n);function tu(s,e){const t=this||Co,n=e||t,i=_n.from(n.headers);let r=n.data;return se.forEach(s,function(o){r=o.call(t,r,i.normalize(),e?e.status:void 0)}),i.normalize(),r}function am(s){return!!(s&&s.__CANCEL__)}function Ar(s,e,t){ $ e.call(this,s??"canceled", $ e.ERR_CANCELED,e,t),this.name="CanceledError"}se.inherits(Ar, $ e,{__CANCEL__:!0});function lm(s,e,t){const n=t.config.validateStatus;!t.status||!n||n(t.status)?s(t):e(new $ e("Request failed with status code "+t.status,[ $ e.ERR_BAD_REQUEST, $ e.ERR_BAD_RESPONSE][Math.floor(t.status/100)-4],t.config,t.request,t))}function XM(s){const e=/^([-+ \w ]{1,25})(:? \/ \/ |:)/.exec(s);return e&&e[1]||""}function jM(s,e){s=s||10;const t=new Array(s),n=new Array(s);let i=0,r=0,o;return e=e!==void 0?e:1e3,function(a){const l=Date.now(),c=n[r];o||(o=l),t[i]=a,n[i]=l;let h=r,u=0;for(;h!==i;)u+=t[h++],h=h%s;if(i=(i+1)%s,i===r&&(r=(r+1)%s),l-o<e)return;const d=c&&l-c;return d?Math.round(u*1e3/d):void 0}}function ZM(s,e){let t=0,n=1e3/e,i,r;const o=(a,l=Date.now())=>{t=l,i=null,r&&(clearTimeout(r),r=null),s(...a)};return[(...a)=>{const l=Date.now(),c=l-t;c>=n?o(a,l):(i=a,r||(r=setTimeout(()=>{r=null,o(i)},n-c)))},()=>i&&o(i)]}const sl=(s,e,t=3)=>{let n=0;const i=jM(50,250);return ZM(r=>{const o=r.loaded,a=r.lengthComputable?r.total:void 0,l=o-n,c=i(l),h=o<=a;n=o;const u={loaded:o,total:a,progress:a?o/a:void 0,bytes:l,rate:c||void 0,estimated:c&&a&&h?(a-o)/c:void 0,event:r,lengthComputable:a!=null,[e?"download":"upload"]:!0};s(u)},t)},cm=(s,e)=>{const t=s!=null;return[n=>e[0]({lengthComputable:t,total:s,loaded:n}),e[1]]},hm=s=>(...e)=>se.asap(()=>s(...e)),qM=rn.hasStandardBrowserEnv?((s,e)=>t=>(t=new URL(t,rn.origin),s.protocol===t.protocol&&s.host===t.host&&(e||s.port===t.port)))(new URL(rn.origin),rn.navigator&&/(msie|trident)/i.test(rn.navigator.userAgent)):()=>!0,YM=rn.hasStandardBrowserEnv?{write(s,e,t,n,i,r,o){if(typeof document>"u")return;const a=[ ` $ { s } = $ { encodeURIComponent ( e ) } ` ];se.isNumber(t)&&a.push( ` expires = $ { new Date ( t ) . toUTCString ( ) } ` ),se.isString(n)&&a.push( ` path = $ { n } ` ),se.isString(i)&&a.push( ` domain = $ { i } ` ),r===!0&&a.push("secure"),se.isString(o)&&a.push( ` SameSite = $ { o } ` ),document.cookie=a.join("; ")},read(s){if(typeof document>"u")return null;const e=document.cookie.match(new RegExp("(?:^|; )"+s+"=([^;]*)"));return e?decodeURIComponent(e[1]):null},remove(s){this.write(s,"",Date.now()-864e5,"/")}}:{write(){},read(){return null},remove(){}};function KM(s){return/^([a-z][a-z \d + \- .]*:)? \/ \/ /i.test(s)}function $ M(s,e){return e?s.replace(/ \/ ? \/ $ /,"")+"/"+e.replace(/^ \/ +/,""):s}function um(s,e,t){let n=!KM(e);return s&&(n||t==!1)? $ M(s,e):e}const dm=s=>s instanceof _n?{...s}:s;function ys(s,e){e=e||{};const t={};function n(c,h,u,d){return se.isPlainObject(c)&&se.isPlainObject(h)?se.merge.call({caseless:d},c,h):se.isPlainObject(h)?se.merge({},h):se.isArray(h)?h.slice():h}function i(c,h,u,d){if(se.isUndefined(h)){if(!se.isUndefined(c))return n(void 0,c,u,d)}else return n(c,h,u,d)}function r(c,h){if(!se.isUndefined(h))return n(void 0,h)}function o(c,h){if(se.isUndefined(h)){if(!se.isUndefined(c))return n(void 0,c)}else return n(void 0,h)}function a(c,h,u){if(u in e)return n(c,h);if(u in s)return n(void 0,c)}const l={url:r,method:r,data:r,baseURL:o,transformRequest:o,transformResponse:o,paramsSerializer:o,timeout:o,timeoutMessage:o,withCredentials:o,withXSRFToken:o,adapter:o,responseType:o,xsrfCookieName:o,xsrfHeaderName:o,onUploadProgress:o,o
` +o.map(ym).join( `
` ):" "+ym(o[0]):"as no adapter specified";throw new $ e("There is no suitable adapter to dispatch the request "+a,"ERR_NOT_SUPPORT")}return i}const _m={getAdapter:l3,adapters:nu};function iu(s){if(s.cancelToken&&s.cancelToken.throwIfRequested(),s.signal&&s.signal.aborted)throw new Ar(null,s)}function Mm(s){return iu(s),s.headers=_n.from(s.headers),s.data=tu.call(s,s.transformRequest),["post","put","patch"].indexOf(s.method)!==-1&&s.headers.setContentType("application/x-www-form-urlencoded",!1),_m.getAdapter(s.adapter||Co.adapter,s)(s).then(function(e){return iu(s),e.data=tu.call(s,s.transformResponse,e),e.headers=_n.from(e.headers),e},function(e){return am(e)||(iu(s),e&&e.response&&(e.response.data=tu.call(s,s.transformResponse,e.response),e.response.headers=_n.from(e.response.headers))),Promise.reject(e)})}const wm="1.13.2",ol={};["object","boolean","number","function","string","symbol"].forEach((s,e)=>{ol[s]=function(t){return typeof t===s||"a"+(e<1?"n ":" ")+s}});const Sm={};ol.transitional=function(s,e,t){function n(i,r){return"[Axios v"+wm+"] Transitional option '"+i+"'"+r+(t?". "+t:"")}return(i,r,o)=>{if(s===!1)throw new $ e(n(r," has been removed"+(e?" in "+e:"")), $ e.ERR_DEPRECATED);return e&&!Sm[r]&&(Sm[r]=!0,console.warn(n(r," has been deprecated since v"+e+" and will be removed in the near future"))),s?s(i,r,o):!0}},ol.spelling=function(s){return(e,t)=>(console.warn( ` $ { t } is likely a misspelling of $ { s } ` ),!0)};function c3(s,e,t){if(typeof s!="object")throw new $ e("options must be an object", $ e.ERR_BAD_OPTION_VALUE);const n=Object.keys(s);let i=n.length;for(;i-- >0;){const r=n[i],o=e[r];if(o){const a=s[r],l=a===void 0||o(a,r,s);if(l!==!0)throw new $ e("option "+r+" must be "+l, $ e.ERR_BAD_OPTION_VALUE);continue}if(t!==!0)throw new $ e("Unknown option "+r, $ e.ERR_BAD_OPTION)}}const al={assertOptions:c3,validators:ol},ci=al.validators;let _s=class{constructor(s){this.defaults=s||{},this.interceptors={request:new im,response:new im}}async request(s,e){try{return await this._request(s,e)}catch(t){if(t instanceof Error){let n={};Error.captureStackTrace?Error.captureStackTrace(n):n=new Error;const i=n.stack?n.stack.replace(/^.+ \n /,""):"";try{t.stack?i&&!String(t.stack).endsWith(i.replace(/^.+ \n .+ \n /,""))&&(t.stack+= `
` +i):t.stack=i}catch{}}throw t}}_request(s,e){typeof s=="string"?(e=e||{},e.url=s):e=s||{},e=ys(this.defaults,e);const{transitional:t,paramsSerializer:n,headers:i}=e;t!==void 0&&al.assertOptions(t,{silentJSONParsing:ci.transitional(ci.boolean),forcedJSONParsing:ci.transitional(ci.boolean),clarifyTimeoutError:ci.transitional(ci.boolean)},!1),n!=null&&(se.isFunction(n)?e.paramsSerializer={serialize:n}:al.assertOptions(n,{encode:ci.function,serialize:ci.function},!0)),e.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?e.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:e.allowAbsoluteUrls=!0),al.assertOptions(e,{baseUrl:ci.spelling("baseURL"),withXsrfToken:ci.spelling("withXSRFToken")},!0),e.method=(e.method||this.defaults.method||"get").toLowerCase();let r=i&&se.merge(i.common,i[e.method]);i&&se.forEach(["delete","get","head","post","put","patch","common"],f=>{delete i[f]}),e.headers=_n.concat(r,i);const o=[];let a=!0;this.interceptors.request.forEach(function(f){typeof f.runWhen=="function"&&f.runWhen(e)===!1||(a=a&&f.synchronous,o.unshift(f.fulfilled,f.rejected))});const l=[];this.interceptors.response.forEach(function(f){l.push(f.fulfilled,f.rejected)});let c,h=0,u;if(!a){const f=[Mm.bind(this),void 0];for(f.unshift(...o),f.push(...l),u=f.length,c=Promise.resolve(e);h<u;)c=c.then(f[h++],f[h++]);return c}u=o.length;let d=e;for(;h<u;){const f=o[h++],g=o[h++];try{d=f(d)}catch(p){g.call(this,p);break}}try{c=Mm.call(this,d)}catch(f){return Promise.reject(f)}for(h=0,u=l.length;h<u;)c=c.then(l[h++],l[h++]);return c}getUri(s){s=ys(this.defaults,s);const e=um(s.baseURL,s.url,s.allowAbsoluteUrls);return nm(e,s.params,s.paramsSerializer)}};se.forEach(["delete","get","head","options"],function(s){_s.prototype[s]=function(e,t){return this.request(ys(t||{},{method:s,url:e,data:(t||{}).data}))}}),se.forEach(["post","put","patch"],function(s){function e(t){return function(n,i,r){return this.request(ys(r||{},{method:s,headers:t?{"Content-Type":"multipart/form-data"}:{},url:n,data:i}))}}_s.prototype[s]=e(),_s.prototype[s+"Form"]=e(!0)});let h3=class q0{constructor(e){if(typeof e!="function")throw new TypeError("executor must be a function.");let t;this.promise=new Promise(function(i){t=i});const n=this;this.promise.then(i=>{if(!n._listeners)return;let r=n._listeners.length;for(;r-- >0;)n._listeners[r](i);n._listeners=null}),this.promise.then=i=>{let r;const o=new Promise(a=>{n.subscribe(a),r=a}).then(i);return o.cancel=function(){n.unsubscribe(r)},o},e(function(i,r,o){n.reason||(n.reason=new Ar(i,r,o),t(n.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(e){if(this.reason){e(this.reason);return}this._listeners?this._listeners.push(e):this._listeners=[e]}unsubscribe(e){if(!this._listeners)return;const t=this._listeners.indexOf(e);t!==-1&&this._listeners.splice(t,1)}toAbortSignal(){const e=new AbortController,t=n=>{e.abort(n)};return this.subscribe(t),e.signal.unsubscribe=()=>this.unsubscribe(t),e.signal}static source(){let e;return{token:new q0(function(t){e=t}),cancel:e}}};function u3(s){return function(e){return s.apply(null,e)}}function d3(s){return se.isObject(s)&&s.isAxiosError===!0}const su={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:4
` );this.workerSourceURL=URL.createObjectURL(new Blob([o]))}),this.decoderPending}_getWorker(e,t){return this._initDecoder().then(()=>{if(this.workerPool.length<this.workerLimit){const i=new Worker(this.workerSourceURL);i._callbacks={},i._taskCosts={},i._taskLoad=0,i.postMessage({type:"init",decoderConfig:this.decoderConfig}),i.onmessage=function(r){const o=r.data;switch(o.type){case"decode":i._callbacks[o.id].resolve(o);break;case"error":i._callbacks[o.id].reject(o);break;default:console.error('THREE.DRACOLoader: Unexpected message, "'+o.type+'"')}},this.workerPool.push(i)}else this.workerPool.sort(function(i,r){return i._taskLoad>r._taskLoad?-1:1});const n=this.workerPool[this.workerPool.length-1];return n._taskCosts[e]=t,n._taskLoad+=t,n})}_releaseTask(e,t){e._taskLoad-=e._taskCosts[t],delete e._callbacks[t],delete e._taskCosts[t]}debug(){console.log("Task load: ",this.workerPool.map(e=>e._taskLoad))}dispose(){for(let e=0;e<this.workerPool.length;++e)this.workerPool[e].terminate();return this.workerPool.length=0,this.workerSourceURL!==""&&URL.revokeObjectURL(this.workerSourceURL),this}}function m3(){let s,e;onmessage=function(o){const a=o.data;switch(a.type){case"init":s=a.decoderConfig,e=new Promise(function(h){s.onModuleLoaded=function(u){h({draco:u})},DracoDecoderModule(s)});break;case"decode":const l=a.buffer,c=a.taskConfig;e.then(h=>{const u=h.draco,d=new u.Decoder;try{const f=t(u,d,new Int8Array(l),c),g=f.attributes.map(p=>p.array.buffer);f.index&&g.push(f.index.array.buffer),self.postMessage({type:"decode",id:a.id,geometry:f},g)}catch(f){console.error(f),self.postMessage({type:"error",id:a.id,error:f.message})}finally{u.destroy(d)}});break}};function t(o,a,l,c){const h=c.attributeIDs,u=c.attributeTypes;let d,f;const g=a.GetEncodedGeometryType(l);if(g===o.TRIANGULAR_MESH)d=new o.Mesh,f=a.DecodeArrayToMesh(l,l.byteLength,d);else if(g===o.POINT_CLOUD)d=new o.PointCloud,f=a.DecodeArrayToPointCloud(l,l.byteLength,d);else throw new Error("THREE.DRACOLoader: Unexpected geometry type.");if(!f.ok()||d.ptr===0)throw new Error("THREE.DRACOLoader: Decoding failed: "+f.error_msg());const p={index:null,attributes:[]};for(const x in h){const m=self[u[x]];let b,v;if(c.useUniqueIDs)v=h[x],b=a.GetAttributeByUniqueId(d,v);else{if(v=a.GetAttributeId(d,o[h[x]]),v===-1)continue;b=a.GetAttribute(d,v)}const y=i(o,a,d,x,m,b);x==="color"&&(y.vertexColorSpace=c.vertexColorSpace),p.attributes.push(y)}return g===o.TRIANGULAR_MESH&&(p.index=n(o,a,d)),o.destroy(d),p}function n(o,a,l){const c=l.num_faces()*3,h=c*4,u=o._malloc(h);a.GetTrianglesUInt32Array(l,h,u);const d=new Uint32Array(o.HEAPF32.buffer,u,c).slice();return o._free(u),{array:d,itemSize:1}}function i(o,a,l,c,h,u){const d=l.num_points(),f=u.num_components(),g=r(o,h),p=f*h.BYTES_PER_ELEMENT,x=Math.ceil(p/4)*4,m=x/h.BYTES_PER_ELEMENT,b=d*p,v=d*x,y=o._malloc(b);a.GetAttributeDataArrayForAllPoints(l,u,g,b,y);const M=new h(o.HEAPF32.buffer,y,b/h.BYTES_PER_ELEMENT);let E;if(p===x)E=M.slice();else{E=new h(v/h.BYTES_PER_ELEMENT);let A=0;for(let R=0,_=M.length;R<_;R++){for(let S=0;S<f;S++)E[A+S]=M[R*f+S];A+=m}}return o._free(y),{name:c,count:d,itemSize:f,array:E,stride:m}}function r(o,a){switch(a){case Float32Array:return o.DT_FLOAT32;case Int8Array:return o.DT_INT8;case Int16Array:return o.DT_INT16;case Int32Array:return o.DT_INT32;case Uint8Array:return o.DT_UINT8;case Uint16Array:return o.DT_UINT16;case Uint32Array:return o.DT_UINT32}}}var Cr=(s=>(s.ModelLoadStart="model-load-start",s.ModelLoadProgress="model-load-progress",s.ModelLoaded="model-loaded",s.ModelError="model-error",s.SelectionChanged="selection-changed",s.HoverChanged="hover-changed",s.Click="click",s.MouseMove="mouse-move",s.CameraChanged="camera-changed",s.CameraIdle="camera-idle",s.ViewportResize="viewport-resize",s.EngineFree="engine-free",s.EngineBusy="engine-busy",s))(Cr||{});function g3(s,e,t,n){let i=0,r=0,o=0,a=s.models.find(f=>f.url==t),l=e.circularMeps,c=e.rectMeps.filter(f=>f.type==="风管"),h=e.rectMeps.filter(f=>f.type==="桥架"),u=e.ellipseMeps,d=s.scene;if(new Xt,new ht,l&&l.length){let f=[],g=0;for(let p
2026-01-28 12:00:55 +08:00
1. 网络连接
2. API地址是否正确
3. 是否有CORS限制 ` ):i}}async chatStream(e,t){const n=new AbortController,i=setTimeout(()=>n.abort(),this.config.timeout);try{const r=await fetch( ` $ { this . config . baseURL } / chat / completions ` ,{method:"POST",headers:{"Content-Type":"application/json",Authorization: ` Bearer $ { this . config . apiKey } ` },body:JSON.stringify({model:this.config.model,messages:e,temperature:this.config.temperature,max_tokens:this.config.maxTokens,stream:!0}),signal:n.signal});if(clearTimeout(i),!r.ok){const c=await r.json().catch(()=>({}));throw new Error( ` API请求失败 ( $ { r . status } ) : $ { c . error ? . message || c . message || r . statusText } ` )}const o=r.body?.getReader();if(!o)throw new Error("无法读取响应流");const a=new TextDecoder;let l="";for(;;){const{done:c,value:h}=await o.read();if(c){t("",!0);break}l+=a.decode(h,{stream:!0});const u=l.split( `
2026-01-28 18:40:46 +08:00
` );l=u.pop()||"";for(const d of u){const f=d.trim();if(!f||!f.startsWith("data: "))continue;const g=f.slice(6);if(g!=="[DONE]")try{const p=JSON.parse(g).choices?.[0]?.delta?.content;p&&t(p,!1)}catch(p){console.warn("解析流式数据失败:",p)}}}}catch(r){throw clearTimeout(i),r.name==="AbortError"?new Error("请求超时,请重试"):r.message.includes("Failed to fetch")?new Error("网络请求失败,请检查网络连接"):r}}updateConfig(e){this.config={...this.config,...e}}getConfig(){return{...this.config}}}class DE{engine;steps=[];stepResults=new Map;conversationHistory=[];state="idle";llmApi=null;config=null;_callback_message;_callback_question;_callback_content;prompts={};constructor(e){this.engine=e}async init(e,t,n){this._callback_message=e,this._callback_question=t,this._callback_content=n,this.conversationHistory=[];let i={llmConfig:{baseURL:"https://open.bigmodel.cn/api/coding/paas/v4",apiKey:"4041336a72f14d8fa3800bd651a80fec.vZWUxssXOXB37vlV",model:"GLM-4.5-Air",temperature:.7,maxTokens:2e3},debug:!0,stepExecution:{maxRetries:5},prompts:{main:"",step:"",apiDoc:""}};try{this.config=i,this.llmApi=new LE(i.llmConfig);try{const r=await Promise.resolve().then(()=>xT);this.prompts.main=r.default;const o=await Promise.resolve().then(()=>vT);this.prompts.step=o.default;const a=await Promise.resolve().then(()=>bT);this.prompts.apiDoc=a.default}catch(r){throw console.error("[AI Manager] 提示词文件加载失败:",r),new Error( ` 提示词文件加载失败 : $ { r . message || "未知错误" } ` )}}catch(r){throw console.error("[AI Manager] 初始化失败:",r),r}}async conversationV2(e){if(this.conversationHistory.length===0){const i={role:"system",content: ` $ { this . prompts . main } ` },r={role:"system",content: ` # # BIM引擎API文档
2026-01-28 12:00:55 +08:00
$ { this . prompts . apiDoc } ` };this.conversationHistory.push(i),this.conversationHistory.push(r)}this.conversationHistory.push({role:"user",content:e});const t=await this.llmApi.chat(this.conversationHistory);this.conversationHistory.push({role:"assistant",content:t}),this.config?.debug&&console.log("[AI Manager] 大模型响应:",t);let n=await this.parseAnalysisResponse(t);n&&n.questions&&n.questions.length>0&&this._callback_question(n.questions)}async parseAnalysisResponse(e){try{if(e.includes("##question##")){const t=e.match(/##question## \s *([ \s \S ]*?)(?=##| $ )/);if(t){let n=t[1].trim();n=n.replace(/^ ` ` ` json \ n ? /,"").replace(/ ^ ` ` ` \n ?/,"").replace(/ \n ? ` ` ` $ / , "" ) ; const i = n . match ( /(\[[\s\S]*\])/ ) ; i && ( n = i [ 1 ] ) ; const r = JSON . parse ( n ) ; return this . state = "waiting_answer" , { state : "waiting_answer" , questions : r } } } if ( e . includes ( "##steps##" ) ) { const t = e . match ( /##steps##\s*([\s\S]*?)(?=##|$)/ ) ; if ( t ) { let n = t [ 1 ] . trim ( ) ; n = n . replace ( /^```json\n?/ , "" ) . replace ( /^```\n?/ , "" ) . replace ( /\n?```$/ , "" ) ; const i = n . match ( /(\[[\s\S]*\])/ ) ; return i && ( n = i [ 1 ] ) , this . steps = JSON . parse ( n ) , this . config ? . debug && console . log ( "[AI Manager] 步骤规划完成,共" , this . steps . length , "个步骤" ) , this . _callback _message ( this . steps ) , await this . executeSteps ( ) } } return { state : "completed" , data : e } } catch ( t ) { return console . error ( "[AI Manager] 解析响应失败:" , t ) , { state : "error" , error : "解析大模型响应失败: " + t . message } } } async executeSteps ( ) { try { this . state = "executing" , this . stepResults . clear ( ) ; for ( const e of this . steps ) { this . _callback _message ( e ) , this . config ? . debug && console . log ( ` [AI Manager] 执行步骤 ${ e . id } : ${ e . content } ` ) ; const t = await this . getDependenciesOutput ( e . dependencies ) , n = await this . executeStep ( e , t ) ; this . stepResults . set ( e . id , n ) , this . config ? . debug && console . log ( ` [AI Manager] 步骤 ${ e . id } 执行完成: ` , n ) } return this . state = "completed" , { state : "completed" , steps : this . steps , result : Array . from ( this . stepResults . values ( ) ) } } catch ( e ) { return console . error ( "[AI Manager] 步骤执行失败:" , e ) , { state : "error" , error : "步骤执行失败: " + e . message } } } async getDependenciesOutput ( e ) { return e . length === 0 ? null : e . length === 1 ? this . stepResults . get ( e [ 0 ] ) : e . map ( t => this . stepResults . get ( t ) ) } async executeStep ( e , t ) { const n = this . config ? . stepExecution ? . maxRetries ? ? 1 , i = [ ] ; let r = null , o = ! 1 ; for ( let a = 0 ; a <= n ; a ++ ) try { const l = i . length > 0 ? i [ i . length - 1 ] : "" , c = await ( a === 0 ? this . generateCode ( e , t ) : o ? this . regenerateCodeAfterFailure ( e , t , l , r , a ) : this . generateCode ( e , t ) ) ; i . push ( c ) , this . config ? . debug && console . log ( ` [AI Manager] 步骤 ${ e . id } 第 ${ a + 1 } 次生成的代码:
$ { c } ` );try{const h=await this.executeCode(c,t);if(h instanceof Object&&h.success==!1||h instanceof String&&(h.includes("undefined")||h.includes("not"))){r=h,o=!0;debugger;throw h}debugger;return h}catch(h){debugger;throw r=h,o=!0,h}}catch(l){if(o||(r=l),a>=n)throw console.error( ` [ AI Manager ] 执行步骤 $ { e . id } 失败 ( 已达重试上限 ) : ` ,l),new Error( ` 步骤 $ { e . id } ( $ { e . content } ) 执行失败 : $ { l . message } ` );console.warn( ` [ AI Manager ] 步骤 $ { e . id } 第 $ { a + 1 } 次执行失败 , 将尝试让AI修复后重试 ( 剩余重试次数 : $ { n - a } ) : ` ,l)}throw new Error( ` 步骤 $ { e . id } ( $ { e . content } ) 执行失败 : 未知错误 ` )}extractCodeFromResponse(e){const t=e.match(/##code## \s *([ \s \S ]*?)(?=##| $ )/);if(t){let o=t[1].trim();if(o=o.replace(/^ ` ` ` javascript \ n ? /,"").replace(/ ^ ` ` ` js \n ?/,"").replace(/^ ` ` ` \ n ? /,"").replace(/ \ n ? ` ` ` $ /,""),o.length>0)return o}const n=[/ ` ` ` javascript \ s * ( [ \ s \ S ] * ? ) ` ` ` /i,/ ` ` ` js \ s * ( [ \ s \ S ] * ? ) ` ` ` /i,/ ` ` ` \ s * ( [ \ s \ S ] * ? ) ` ` ` /];for(const o of n){const a=e.match(o);if(a&&a[1]){const l=a[1].trim();if(l.length>0)return this.config?.debug&&console.warn("[AI Manager] 未找到 ##code## 标记,从 markdown 代码块中提取代码"),l}}const i=/[请|说明|注意|需要|应该|可以|如果|但是|因为|所以|例如|比如]/i.test(e),r=/(function|const|let|var|return|async|await|=>|engine \. |previousStepOutput)/.test(e);if(!i&&r){const o=e.trim().replace(/^[,。:;!? \s ]+/,"").replace(/[,。:;!? \s ]+ $ /,"");if(o.length>10)return this.config?.debug&&console.warn("[AI Manager] 未找到 ##code## 标记和代码块,尝试使用整个响应作为代码"),o}throw new Error( ` 无法从大模型响应中提取代码 。 响应内容 : $ { e . substring ( 0 , 200 ) } ... ` )}async generateCode(e,t){try{const n={role:"system",content: ` $ { this . prompts . step } ` },i={role:"system",content: `
# # BIM引擎API文档
$ { this . prompts . apiDoc } ` },r={role:"user",content: ` 请根据以下步骤描述生成可执行的JavaScript代码 :
步骤信息 :
$ { JSON . stringify ( e , null , 2 ) }
前序步骤输出数据 :
$ { t ? JSON . stringify ( t , null , 2 ) : "null" }
请严格按照 # # code # # 格式输出代码 。 ` },o=[n,i,r],a=await this.llmApi.chat(o);return this.extractCodeFromResponse(a)}catch(n){throw console.error("[AI Manager] 代码生成失败:",n),n}}async regenerateCodeAfterFailure(e,t,n,i,r){try{const o={role:"system",content: ` $ { this . prompts . step } ` },a={role:"system",content: `
# # BIM引擎API文档
$ { this . prompts . apiDoc } ` },l={message:i?.message||(i instanceof Object?JSON.stringify(i):String(i)),name:i?.name,stack:i?.stack},c={role:"user",content: ` 上一次生成的代码在执行时失败了 , 请你修复后重新输出完整可执行的 JavaScript 代码 ( 仍然要严格按 # # code # # 格式输出 ) 。
当前步骤信息 :
$ { JSON . stringify ( e , null , 2 ) }
前序步骤输出数据 :
$ { t ? JSON . stringify ( t , null , 2 ) : "null" }
上一次生成的代码 :
$ { n ? `
\ ` \` \` javascript
$ { n }
\ ` \` \`
` : `
( 无 )
` }
执行错误信息 ( 第 $ { r } 次重试前 ) :
$ { JSON . stringify ( l , null , 2 ) }
修复要求 ( 请务必遵守 ) :
1 ) 不要输出解释文字 , 只输出 # # code # # 段落里的代码
2 ) 如果是语法错误 / 引用未定义 / 缺少 await / 返回值不一致 , 请直接修复
3 ) 尽量保持与步骤目标一致 , 避免引入与步骤无关的副作用
4 ) 代码需要能在浏览器环境运行 ( 不要使用 Node 专属 API ) ` },h=await this.llmApi.chat([o,a,c]);try{return this.extractCodeFromResponse(h)}catch(u){throw new Error( ` 无法从大模型响应中提取代码 ( 修复重试阶段 ) : $ { u . message } ` )}}catch(o){throw console.error("[AI Manager] 修复后代码生成失败:",o),o}}async executeCode(e,t){try{const n=this.engine;let i=e;i=i.replace(/ \b (const|let|var) \s +previousStepOutput \s *= \s *[^;]*;/g,""),i=i.replace(/ \b (const|let|var) \s +previousStepOutput \s *;/g,"");const r=new Function("engine","previousStepOutput", `
'use strict' ;
$ { i }
2026-01-28 18:40:46 +08:00
` )(n,t);return r&&typeof r.then=="function"?await r:r}catch(n){return console.error("[AI Manager] 代码执行失败:",n),"error"+n.message}}reset(){this.conversationHistory=[],this.steps=[],this.stepResults.clear(),this.state="idle",this.config?.debug&&console.log("[AI Manager] 对话已重置")}getState(){return this.state}getHistory(){return[...this.conversationHistory]}getSteps(){return[...this.steps]}getStepResults(){return new Map(this.stepResults)}}class IE{options;DeviceType;animationId=null;isRenderingPaused=!1;controlsEnabledBeforePause=!0;animate;onWindowResize;scene;camera;renderer;sceneModule;cameraModule;deviceModule;renderModule;controlModule;composerModule;loaderModule;engineStatus;events;lightModule;interactionModule;modelToolModule;worldToScreen;handelBehaved;octreeBox;controls;stats;catchSvg;viewCube;rangeScale;setting;measure;clipping;modelTree;engineInfo;modelProperties;modelMapperBatch;modelEdge;ai;models=[];reactBoundingClientRect={left:0,top:0};container;constructor(e){if(this.options=e,this.container=document.getElementById(e.containerId),!this.container)throw new Error( ` Container $ { e . containerId } not found ` );this.ai=new DE(this),this.deviceModule=new s2(this),this.DeviceType=this.deviceModule.getDeviceType(),this.cameraModule=new i2(this),this.sceneModule=new n2(this),this.scene=this.sceneModule.scene,this.renderModule=new r2(this),this.renderer=this.renderModule.createRenderer(),this.camera=this.cameraModule.orthographicCamera,this.scene.camera=this.camera,this.controlModule=new y2(this),this.controlModule.switchDefaultMode(),this.controls=this.controlModule.orbitControls,this.composerModule=new N2(this),this.composerModule.init(),this.events=new ow,this.engineStatus=new rw(this),this.engineStatus.init(),this.loaderModule=new sw(this),this.lightModule=new aw(this),this.lightModule.init(),this.viewCube=new bw(this),this.viewCube.init(),this.octreeBox=yw(this),this.rangeScale=new _w(this),this.rangeScale.init(),this.clipping=new EE(this),this.clipping.init(),this.setting=new Mw(this),this.setting.init(),this.handelBehaved=jh(this),this.modelMapperBatch=new PE(this),this.measure=new Lw(this),this.modelToolModule=new cw(this),this.modelProperties=new CE(this),this.interactionModule=new lw(this),this.interactionModule.init(),this.interactionModule.active(),this.modelEdge=new RE(this),this.modelTree=new TE(this),this.engineInfo=new AE(this),this.worldToScreen=new Un(this.camera,this.renderer,this.scene),this.stats=new fw,this.stats.showPanel(0),this.stats.dom.style.position="absolute",this.stats.dom.style.top="0px",this.stats.dom.style.left="0px",this.stats.dom.style.zIndex="1000",this.container.appendChild(this.stats.dom);let t=document.createElementNS("http://www.w3.org/2000/svg","svg");t.style.position="absolute",t.style.width="100%",t.style.height="100%",t.style.zIndex="1000",t.style.left="0px",t.style.top="0px",t.style.pointerEvents="none";const n=this.renderer?.domElement.width||1920,i=this.renderer?.domElement.height||1080;t.setAttribute("viewBox", ` 0 0 $ { n } $ { i } ` ),t.setAttribute("preserveAspectRatio","none"),this.container.appendChild(t),this.catchSvg=t,this.onWindowResize=()=>{this.handleWindowResize()},window.addEventListener("resize",this.onWindowResize),this.animate=()=>{if(!this.isRenderingPaused)this.animationId=requestAnimationFrame(this.animate);else{this.animationId=null;return}this.stats&&this.stats.begin(),this.composerModule&&this.composerModule.composer.render(),this.viewCube.cubeTool.RenderScene(),this.measure.update(),this.controlModule.update(),this.stats&&this.stats.end()},this.animate()}pauseRendering(){if(this.isRenderingPaused){console.warn("[BimEngine] Rendering is already paused");return}this.isRenderingPaused=!0,this.controls&&(this.controlsEnabledBeforePause=this.controls.enabled,this.controls.enabled=!1)}resumeRendering(){if(!this.isRenderingPaused){console.warn("[BimEngine] Rendering is not paused");return}this.isRenderingPaused=!1,this.controls&&(this.controls.enabled=this.controlsEnabledBeforePause),this.animationId===null&&this.animate()}isRenderingPau
2026-01-22 11:29:51 +08:00
< svg viewBox = "0 0 24 24" aria - hidden = "true" >
< circle cx = "12" cy = "12" r = "9" > < / c i r c l e >
< / s v g >
2026-01-28 18:40:46 +08:00
` ;for(let p=0;p<i.length;p++){const x=i[p],m=document.createElement("button");m.type="button",m.className="bim-measure-tool-btn",m.dataset.mode=x;const b=document.createElement("span");b.className="bim-measure-tool-icon",b.innerHTML=VE[x]||r,m.appendChild(b),m.addEventListener("click",()=>{this.setActiveMode(x)}),this.toolButtons.set(x,m),n.appendChild(m)}t.appendChild(n);const o=document.createElement("div");o.className="bim-measure-toggle",this.toggleBtn=document.createElement("button"),this.toggleBtn.type="button",this.toggleBtn.className="bim-measure-toggle-btn",this.toggleTextEl=document.createElement("span"),this.toggleTextEl.className="bim-measure-toggle-text";const a=document.createElement("span");a.className="bim-measure-toggle-icon",a.innerHTML= `
2026-01-22 11:29:51 +08:00
< svg viewBox = "0 0 24 24" aria - hidden = "true" >
< path d = "M7 10l5 5 5-5z" > < / p a t h >
< / s v g >
2026-01-28 18:40:46 +08:00
` ,this.toggleBtn.appendChild(this.toggleTextEl),this.toggleBtn.appendChild(a),this.toggleBtn.addEventListener("click",()=>{this.isExpanded=!this.isExpanded,this.applyExpandedState(),this.setLocales(),this.options.onExpandedChange&&this.options.onExpandedChange(this.isExpanded)}),o.appendChild(this.toggleBtn),t.appendChild(o),this.mainViewEl.appendChild(t);const l=document.createElement("div");l.className="bim-measure-result";const c=document.createElement("div");c.className="bim-measure-row";const h=document.createElement("span");h.className="label",this.mainValueLabelEl=h;const u=document.createElement("span");u.className="value",this.mainValueValueEl=u,this.mainNumberEl=document.createElement("span"),this.mainNumberEl.className="bim-measure-main-number",this.mainUnitEl=document.createElement("span"),this.mainUnitEl.className="bim-measure-main-unit",this.mainValueValueEl.appendChild(this.mainNumberEl),this.mainValueValueEl.appendChild(document.createTextNode(" ")),this.mainValueValueEl.appendChild(this.mainUnitEl),c.appendChild(h),c.appendChild(u),l.appendChild(c);const d=document.createElement("div");d.className="bim-measure-xyz",this.xyzBoxEl=d;const f=(p,x,m)=>{const b=document.createElement("div");b.className="bim-measure-row";const v=document.createElement("span");v.className="label",v.dataset.i18nKey=p;const y=document.createElement("span");return y.className= ` value $ { x } ` ,m(y),b.appendChild(v),b.appendChild(y),b};d.appendChild(f("measure.labels.x","bim-measure-xyz-x",p=>this.xyzXEl=p)),d.appendChild(f("measure.labels.y","bim-measure-xyz-y",p=>this.xyzYEl=p)),d.appendChild(f("measure.labels.z","bim-measure-xyz-z",p=>this.xyzZEl=p)),l.appendChild(d),this.mainViewEl.appendChild(l);const g=document.createElement("div");return g.className="bim-measure-footer",this.clearBtn=document.createElement("button"),this.clearBtn.type="button",this.clearBtn.className="bim-measure-clear-btn",this.clearBtn.addEventListener("click",()=>{this.clearAll()}),this.settingsBtn=document.createElement("button"),this.settingsBtn.type="button",this.settingsBtn.className="bim-measure-settings-btn",this.settingsBtn.innerHTML= `
2026-01-22 11:29:51 +08:00
< svg viewBox = "0 0 24 24" aria - hidden = "true" >
< path d = "M19.14 12.94c.04-.31.06-.63.06-.94s-.02-.63-.06-.94l2.03-1.58a.5.5 0 0 0 .12-.64l-1.92-3.32a.5.5 0 0 0-.6-.22l-2.39.96a7.27 7.27 0 0 0-1.63-.94l-.36-2.54A.5.5 0 0 0 13.9 1h-3.8a.5.5 0 0 0-.49.42l-.36 2.54c-.58.23-1.12.54-1.63.94l-2.39-.96a.5.5 0 0 0-.6.22L2.71 7.48a.5.5 0 0 0 .12.64l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94L2.83 14.52a.5.5 0 0 0-.12.64l1.92 3.32c.13.22.39.3.6.22l2.39-.96c.5.4 1.05.71 1.63.94l.36 2.54c.04.24.25.42.49.42h3.8c.24 0 .45-.18.49-.42l.36-2.54c.58-.23 1.12-.54 1.63-.94l2.39.96c.22.09.47 0 .6-.22l1.92-3.32a.5.5 0 0 0-.12-.64l-2.03-1.58zM12 15.5A3.5 3.5 0 1 1 12 8a3.5 3.5 0 0 1 0 7.5z" > < / p a t h >
< / s v g >
2026-01-28 18:40:46 +08:00
` ,this.settingsBtn.addEventListener("click",()=>{this.openSettings()}),g.appendChild(this.clearBtn),g.appendChild(this.settingsBtn),this.mainViewEl.appendChild(g),this.settingsViewEl=this.createSettingsDom(),e.appendChild(this.mainViewEl),e.appendChild(this.settingsViewEl),e}createSettingsDom(){const e=document.createElement("div");e.className="bim-measure-settings";const t=document.createElement("div");t.className="bim-measure-settings-title",t.dataset.i18nKey="measure.settings.title",e.appendChild(t);const n=document.createElement("div");n.className="bim-measure-settings-row";const i=document.createElement("div");i.className="label",i.dataset.i18nKey="measure.settings.unit",this.unitSelectEl=document.createElement("select"),this.unitSelectEl.className="bim-measure-settings-select",this.unitSelectEl.appendChild(this.makeOption("m")),this.unitSelectEl.appendChild(this.makeOption("cm")),this.unitSelectEl.appendChild(this.makeOption("mm")),this.unitSelectEl.appendChild(this.makeOption("km")),n.appendChild(i),n.appendChild(this.unitSelectEl),e.appendChild(n);const r=document.createElement("div");r.className="bim-measure-settings-hint",r.dataset.i18nKey="measure.settings.hint",e.appendChild(r);const o=document.createElement("div");o.className="bim-measure-settings-row";const a=document.createElement("div");a.className="label",a.dataset.i18nKey="measure.settings.precision",this.precisionSelectEl=document.createElement("select"),this.precisionSelectEl.className="bim-measure-settings-select",this.precisionSelectEl.appendChild(this.makePrecisionOption(0)),this.precisionSelectEl.appendChild(this.makePrecisionOption(1)),this.precisionSelectEl.appendChild(this.makePrecisionOption(2)),this.precisionSelectEl.appendChild(this.makePrecisionOption(3)),o.appendChild(a),o.appendChild(this.precisionSelectEl),e.appendChild(o);const l=document.createElement("div");return l.className="bim-measure-settings-actions",this.saveSettingsBtn=document.createElement("button"),this.saveSettingsBtn.type="button",this.saveSettingsBtn.className="bim-measure-settings-save",this.saveSettingsBtn.addEventListener("click",()=>{this.saveSettings()}),this.cancelSettingsBtn=document.createElement("button"),this.cancelSettingsBtn.type="button",this.cancelSettingsBtn.className="bim-measure-settings-cancel",this.cancelSettingsBtn.addEventListener("click",()=>{this.cancelSettings()}),l.appendChild(this.saveSettingsBtn),l.appendChild(this.cancelSettingsBtn),e.appendChild(l),this.syncSettingsFormFromConfig(this.config),e}makeOption(e){const t=document.createElement("option");return t.value=e,t.textContent=e,t}makePrecisionOption(e){const t=document.createElement("option");return t.value=String(e),t.textContent=e===0?"0": ` 0. $ { "0" . repeat ( e ) } ` ,t}enterSettingsView(){this.draftConfig={...this.config},this.view="settings",this.syncSettingsFormFromConfig(this.config),this.applyViewState()}saveSettings(){const e=this.unitSelectEl.value||this.config.unit,t=Number(this.precisionSelectEl.value),n={unit:e,precision:this.isValidPrecision(t)?t:this.config.precision};this.config=n,this.saveConfigToCache(n),this.draftConfig=null,this.view="main",this.applyViewState(),this.renderResult(),this.options.onExpandedChange&&this.options.onExpandedChange(this.isExpanded)}cancelSettings(){this.draftConfig&&(this.config={...this.draftConfig}),this.draftConfig=null,this.view="main",this.applyViewState(),this.renderResult(),this.options.onExpandedChange&&this.options.onExpandedChange(this.isExpanded)}syncSettingsFormFromConfig(e){this.unitSelectEl.value=e.unit,this.precisionSelectEl.value=String(e.precision)}applyViewState(){this.view==="settings"?(this.mainViewEl.style.display="none",this.settingsViewEl.style.display="block"):(this.mainViewEl.style.display="block",this.settingsViewEl.style.display="none")}loadConfigFromCache(){try{const e=localStorage.getItem(Vo.CONFIG_CACHE_KEY);if(!e)return null;const t=JSON.parse(e);if(!t||typeof t!="object")return null;const n=t.unit,i=t.precision;return!this.isValidUnit(n)||!this.isValidPrecision(i)?null:{unit:n,precision:i}}catch{return null}}saveConf
2026-01-28 17:19:36 +08:00
# $ { this . dialogId } . bim - collapse - header {
background - color : var ( -- bim - component - bg - hover ) ! important ;
}
# $ { this . dialogId } . bim - collapse - header : hover {
background - color : var ( -- bim - component - bg - active ) ! important ;
}
` ,e.appendChild(i),e}createMaterialsPanel(){const e=document.createElement("div");e.style.cssText="height:100%;overflow-y:auto;";const t=this.propertiesData?.materials||[];if(t.length===0)return e.innerHTML='<div style="padding:20px;text-align:center;color:var(--bim-text-secondary,#999);">无材质数据</div>',e;const n=t.map((r,o)=>({id: ` material - $ { o } ` ,title:r.name|| ` 材质 $ { o + 1 } ` ,content:this.createCategoryContent(r.children||r.properties||[])}));new z0({container:e,accordion:!1,ghost:!0,activeIds:n.length>0?[n[0].id]:[],items:n});const i=document.createElement("style");return i.textContent= `
# $ { this . dialogId } . bim - collapse - header {
background - color : var ( -- bim - component - bg - hover ) ! important ;
}
# $ { this . dialogId } . bim - collapse - header : hover {
background - color : var ( -- bim - component - bg - active ) ! important ;
}
` ,e.appendChild(i),e}createCategoryContent(e){const t=document.createElement("div");return e.forEach((n,i)=>{const r=document.createElement("div");r.style.cssText= `
display : flex ;
border - bottom : 1 px solid var ( -- bim - border - default , rgba ( 255 , 255 , 255 , 0.15 ) ) ;
` ,i===e.length-1&&(r.style.borderBottom="none");const o=document.createElement("div");o.style.cssText= `
width : 120 px ;
flex - shrink : 0 ;
color : var ( -- bim - text - secondary , # 999 ) ;
font - size : 13 px ;
padding : 8 px 12 px ;
border - right : 1 px solid var ( -- bim - border - default , rgba ( 255 , 255 , 255 , 0.15 ) ) ;
` ,o.textContent=n.name||"-";const a=document.createElement("div");a.style.cssText= `
flex : 1 ;
color : var ( -- bim - text - primary , # fff ) ;
font - size : 13 px ;
padding : 8 px 12 px ;
word - break : break - all ;
2026-01-28 18:40:46 +08:00
` ,a.textContent=String(n.value??"-"),r.appendChild(o),r.appendChild(a),t.appendChild(r)}),t}isOpen(){return this.dialog!==null}hide(){this.tabInstance&&(this.tabInstance.destroy(),this.tabInstance=null),this.dialog&&(this.dialog.destroy(),this.dialog=null)}destroy(){this.unsubscribeSelected&&(this.unsubscribeSelected(),this.unsubscribeSelected=null),this.unsubscribeDeselected&&(this.unsubscribeDeselected(),this.unsubscribeDeselected=null),this.hide(),super.destroy()}}class sT{container;wrapper=null;registry;toolbar=null;constructTreeBtn=null;buttonGroup=null;dialog=null;engine=null;rightKey=null;measure=null;sectionPlane=null;sectionAxis=null;sectionBox=null;walkControl=null;map=null;componentDetail=null;constructor(e,t){const n=typeof e=="string"?document.getElementById(e):e;if(!n)throw new Error("Container not found");this.container=n,this.registry=St.getInstance(),t?.locale&&Yt.setLocale(t.locale),t?.theme&&(t.theme==="custom"?console.warn("Custom theme should be set via setCustomTheme()."):rt.setTheme(t.theme)),this.init()}emit(e,t){this.registry.emit(e,t)}on(e,t){return this.registry.on(e,t)}setLocale(e){Yt.setLocale(e)}getLocale(){return Yt.getLocale()}setTheme(e){rt.setTheme(e)}setCustomTheme(e){rt.setCustomTheme(e)}init(){this.container.innerHTML="",this.wrapper=document.createElement("div"),this.wrapper.className="bim-engine-wrapper",this.container.appendChild(this.wrapper),this.registry.container=this.container,this.registry.wrapper=this.wrapper,this.engine=new OE(this.wrapper),this.dialog=new sg(this.wrapper),this.toolbar=new tg(this.wrapper),this.buttonGroup=new ng(this.wrapper),this.rightKey=new U0(this.wrapper),this.constructTreeBtn=new HE(this.wrapper),this.measure=new GE,this.sectionPlane=new XE,this.sectionAxis=new ZE,this.sectionBox=new YE,this.walkControl=new QE,this.walkControl.init(),this.map=new tT,this.map.init(),this.registry.engine3d=this.engine,this.registry.dialog=this.dialog,this.registry.toolbar=this.toolbar,this.registry.buttonGroup=this.buttonGroup,this.registry.rightKey=this.rightKey,this.registry.constructTree=this.constructTreeBtn,this.registry.measure=this.measure,this.registry.sectionPlane=this.sectionPlane,this.registry.sectionAxis=this.sectionAxis,this.registry.sectionBox=this.sectionBox,this.registry.walkControl=this.walkControl,this.registry.map=this.map,this.componentDetail=new iT,this.registry.componentDetail=this.componentDetail,this.componentDetail.init(),this.updateTheme(rt.getTheme()),rt.subscribe(e=>{this.updateTheme(e)})}updateTheme(e){this.wrapper&&(this.wrapper.style.color=e.textPrimary)}destroy(){this.toolbar?.destroy(),this.buttonGroup?.destroy(),this.engine?.destroy(),this.dialog?.destroy(),this.rightKey?.destroy(),this.measure?.destroy(),this.sectionPlane?.destroy(),this.sectionAxis?.destroy(),this.sectionBox?.destroy(),this.walkControl?.destroy(),this.container.innerHTML="",St.reset()}}const rT=Object.freeze(Object.defineProperty({__proto__:null,createHomeButton:()=>({id:"home",groupId:"group-1",type:"button",label:"toolbar.home",icon:It("主视角"),keepActive:!1,onClick:s=>{console.log("首页按钮被点击:",s.id),St.getInstance().engine3d?.CameraGoHome()}})},Symbol.toStringTag,{value:"Module"})),oT=Object.freeze(Object.defineProperty({__proto__:null,createZoomBoxButton:()=>({id:"zoom-box",groupId:"group-1",keepActive:!1,type:"button",label:"toolbar.zoomBox",icon:It("框选放大"),onClick:()=>{St.getInstance().engine3d?.activateZoomBox()}})},Symbol.toStringTag,{value:"Module"})),aT=Object.freeze(Object.defineProperty({__proto__:null,createWalkMenuButton:()=>({id:"walk",groupId:"group-1",type:"button",label:"toolbar.walk",align:"vertical",icon:It("漫游"),onClick:()=>{console.log("漫游按钮被点击"),St.getInstance().walkControl?.show()}})},Symbol.toStringTag,{value:"Module"})),lT=Object.freeze(Object.defineProperty({__proto__:null,createPropertyButton:()=>({id:"property",groupId:"group-1",type:"button",label:"toolbar.property",align:"vertical",icon:It("文档"),onClick:()=>{console.log("构件详情按钮被点击"),St.getInstance().componentDe
2026-01-28 12:00:55 +08:00
# # 角色定位
你是一位资深的 * * AI + BIM轻量化引擎架构专家 * * , 具备以下核心能力 :
1. * * 深度理解BIM引擎架构 * * : 精通BIM引擎的模块化设计 、 API体系 、 数据结构和交互模式
2. * * 需求分析能力 * * : 能够准确理解用户意图 , 识别模糊需求 , 提出精准的澄清问题
3. * * 任务分解能力 * * : 将复杂需求拆解为可执行的 、 原子化的操作步骤
4. * * 技术决策能力 * * : 根据需求特点选择最优的API组合和实现路径
你的职责是通过分析用户需求 , 生成结构化的执行步骤 , 指导代码生成模块完成BIM引擎的功能实现 。
# # 工作流程
如果存在疑问 , 你就不能输出最终的步骤 , 只有当你把所有的疑问清楚后 , 你才可以输出步骤 , 如果存在疑问 , 你要以bim模型为载体 , 不能问一下和bim模型不想干的问题 , 尽量没有或减少问题
# # # 阶段一 : 需求理解与分析
当接收到用户需求时 , 你需要 :
1. * * 深度分析需求 * * :
- 理解用户的核心目标
- 识别涉及到的BIM引擎模块 ( 场景 、 相机 、 模型 、 测量 、 剖切等 )
- 分析数据流向和依赖关系
- 评估需求的复杂度和可行性
2. * * 识别模糊点 * * :
- 检查需求中是否存在歧义 、 缺失信息或边界条件不明确的情况
- 判断是否需要用户澄清才能继续
3. * * 决策是否需要提问 * * :
- * * 仅在必要时提问 * * : 如果需求足够清晰 , 直接进入步骤规划阶段
- * * 避免过度提问 * * : 不要为了提问而提问 , 不要询问可以从上下文推断的信息
- * * 精准提问 * * : 每个问题都应该针对关键决策点 , 影响后续实现路径
# # # 阶段二 : 需求澄清 ( 如需要 )
如果需要用户澄清 , 请按照以下格式输出 :
* * 输出格式 * * :
\ ` \` \`
# # question # #
json内容
\ ` \` \`
* * JSON格式规范 * * :
\ ` \` \` json
[
{
"id" : 0 ,
"question" : "您是否需要设置所有的构件?" ,
"answers" : [
"A. 是的,设置所有构件" ,
"B. 只设置1F层的构件" ,
"C. 根据特定条件筛选构件"
]
} ,
{
"id" : 1 ,
"question" : "颜色设置的优先级是什么?" ,
"answers" : [
"A. 按构件类型设置" ,
"B. 按楼层设置" ,
"C. 按自定义属性设置"
]
}
]
\ ` \` \`
* * 提问原则 * * :
- 每个问题必须针对一个明确的决策点
- 答案选项应该互斥且覆盖主要场景
- 问题数量控制在3个以内 , 优先询问最关键的问题
- 问题描述清晰 、 具体 , 避免模糊表述
- 不要强行提问 , 尽量减少或不提问题
# # # 阶段三 : 步骤规划
当需求清晰后 , 你需要将用户意图拆解为一系列可执行的步骤 。
* * 输出格式 * * :
\ ` \` \`
# # steps # #
json内容
\ ` \` \`
* * JSON格式规范 * * :
\ ` \` \` json
[
{
"id" : 0 ,
"content" : "获取所有桩基模型" ,
"description" : "通过modelTree模块遍历模型树, 筛选出类型为'桩基'的所有构件, 返回构件ID数组和构件对象数组" ,
"output" : "{\\" modelIds \ \ ": [\\" id1 \ \ ", \\" id2 \ \ ", ...], \\" models \ \ ": [modelObject1, modelObject2, ...]}" ,
"dependencies" : [ ] ,
"apiModules" : [ "modelTree" , "dataModule" ]
} ,
{
"id" : 1 ,
"content" : "设置桩基模型颜色为红色" ,
"description" : "使用modelMapperBatch模块的批量设置方法, 将上一步获取的所有桩基模型的颜色属性设置为红色( RGB: 255, 0, 0) " ,
"output" : "{\\" success \ \ ": true, \\" count \ \ ": 10, \\" failedIds \ \ ": []}" ,
"dependencies" : [ 0 ] ,
"apiModules" : [ "modelMapperBatch" ]
}
]
\ ` \` \`
* * 字段说明 * * :
- \ ` id \` : 步骤唯一标识符, 从0开始递增
- \ ` content \` : 步骤的简短描述(一句话概括)
- \ ` description \` : 步骤的详细功能说明,包括:
- 具体要做什么
- 使用哪些API模块
- 如何处理数据
- 可能的边界情况
- \ ` output \` : 步骤输出的数据格式说明( JSON Schema格式) , 用于:
- 指导代码生成模块返回正确的数据结构
- 确保步骤间的数据传递正确
- \ ` dependencies \` : 依赖的步骤ID数组, 表示此步骤需要等待哪些步骤完成
- \ ` apiModules \` : 此步骤涉及到的BIM引擎模块名称数组( 如: modelTree, cameraModule, measure等)
* * 步骤规划原则 * * :
1. * * 原子化 * * : 每个步骤应该只完成一个明确的功能点
2. * * 可执行 * * : 每个步骤都应该能够独立生成可执行的代码
3. * * 依赖清晰 * * : 明确标注步骤间的依赖关系 , 确保执行顺序正确
4. * * 数据流转 * * : 每个步骤的输出格式要明确 , 便于后续步骤使用
5. * * 模块化 * * : 合理利用BIM引擎的模块化设计 , 选择最合适的API
6. * * 错误处理 * * : 在关键步骤中考虑异常情况的处理
# # 硬性要求
# # # 1. 输出格式规范
- * * 必须严格遵循 * * 上述JSON格式 , 字段名称和类型不能改变
- JSON必须是有效的 、 可解析的格式
- 步骤ID必须连续且从0开始
- 依赖关系必须正确 , 不能出现循环依赖
# # # 2. 需求理解要求
- * * 深度理解 * * : 不能停留在表面理解 , 要理解用户的真实意图和业务场景
- * * 上下文感知 * * : 结合BIM引擎的特性 , 理解每个需求在BIM场景下的实际意义
- * * 技术可行性 * * : 确保规划的步骤在BIM引擎API能力范围内
# # # 3. 步骤质量要求
- * * 完整性 * * : 步骤应该覆盖用户需求的所有方面 , 不能遗漏关键环节
- * * 准确性 * * : 步骤描述要准确 , 不能有歧义或错误
- * * 可执行性 * * : 每个步骤都应该能够生成可执行的代码
- * * 效率性 * * : 优先选择高效的API组合 , 避免不必要的中间步骤
# # # 4. 错误预防
- 检查步骤间的数据格式是否匹配
- 确保依赖关系正确 , 避免执行顺序错误
- 验证API模块名称是否正确
- 考虑边界情况和异常处理
# # # 5. 代码生成友好
- 步骤描述要足够详细 , 让代码生成模块能够准确理解意图
- 输出格式说明要具体 , 使用JSON Schema或示例数据
- 明确标注使用的API模块 , 便于代码生成时快速定位
# # 最佳实践
1. * * 先理解后规划 * * : 充分理解需求后再开始规划步骤 , 避免返工
2. * * 模块优先 * * : 优先使用BIM引擎提供的功能模块 , 而不是底层API
3. * * 数据驱动 * * : 明确每个步骤的输入输出 , 确保数据流清晰
4. * * 可扩展性 * * : 考虑未来可能的扩展需求 , 设计灵活的步骤结构
5. * * 用户友好 * * : 步骤描述要清晰易懂 , 便于用户理解整个执行流程
2026-01-28 18:40:46 +08:00
'' ` },Symbol.toStringTag,{value:"Module"})),vT=Object.freeze(Object.defineProperty({__proto__:null,default: ` # BIM引擎AI助手 - 代码生成专家
2026-01-28 12:00:55 +08:00
# # 角色定位
你是一位资深的 * * BIM引擎代码生成专家 * * , 具备以下核心能力 :
1. * * BIM引擎API精通 * * : 深度掌握BIM引擎的所有模块API 、 方法签名 、 参数类型和返回值
2. * * 代码生成能力 * * : 能够根据步骤描述 , 生成高质量 、 可执行 、 符合规范的JavaScript代码
3. * * 上下文理解 * * : 能够理解步骤间的数据流转 , 正确处理前序步骤的输出结果
4. * * 错误处理能力 * * : 具备完善的异常处理和边界情况处理能力
5. * * 代码质量意识 * * : 生成的代码应该具备良好的可读性 、 可维护性和性能
你的职责是根据步骤规划模块提供的步骤描述 , 生成可直接在BIM引擎环境中执行的JavaScript代码片段 。
# # 工作流程
# # # 阶段一 : 理解步骤要求
当接收到步骤执行请求时 , 你需要 :
1. * * 解析步骤信息 * * :
- 理解步骤的 \ ` content \` (简短描述)和 \` description \` (详细说明)
- 识别步骤涉及到的BIM引擎模块 ( \ ` apiModules \` 字段)
- 理解步骤的依赖关系 ( \ ` dependencies \` 字段)
- 明确步骤的预期输出格式 ( \ ` output \` 字段)
2. * * 分析上下文数据 * * :
- 如果有前序步骤的输出结果 , 分析其数据结构
- 理解当前步骤需要使用的输入数据
- 验证数据格式是否匹配步骤要求
3. * * 确定实现方案 * * :
- 根据步骤描述 , 选择最合适的BIM引擎API
- 设计数据转换和处理逻辑
- 规划错误处理策略
# # # 阶段二 : 生成代码
根据步骤要求生成可执行的JavaScript代码 。
* * 输出格式 * * :
\ ` \` \`
# # code # #
[ 可执行的JavaScript代码 ]
\ ` \` \`
* * 代码生成规范 * * :
1. * * 代码结构 * * :
- 代码必须是一个完整的 、 可执行的JavaScript代码片段
- 可以是函数 、 立即执行函数 ( IIFE ) 或代码块
- 代码应该能够直接运行 , 不需要额外的包装
2. * * 引擎实例访问 * * :
- 假设BIM引擎实例通过变量 \ ` engine \` 访问(全局作用域)
- 通过 \ ` engine.moduleName \` 访问各个功能模块
- 例如 : \ ` engine.modelTree \` 、 \` engine.cameraModule \` 、 \` engine.measure \` 等
3. * * 数据输入处理 * * :
- 如果步骤有依赖 , 使用前序步骤的输出数据
- 假设前序步骤的输出数据存储在变量 \ ` previousStepOutput \` 中(如果是第一步,则为 \` null \` )
- 需要根据 \ ` output \` 字段的格式说明,正确解析和使用输入数据
4. * * API调用规范 * * :
- 严格按照BIM引擎API文档使用API
- 参数类型和数量必须正确
- 处理API的返回值和可能的异常
5. * * 数据输出规范 * * :
- 代码执行后 , 必须返回符合步骤 \ ` output \` 字段要求的数据格式
- 使用 \ ` return \` 语句返回结果
- 返回的数据必须是可序列化的 ( JSON格式 )
6. * * 错误处理 * * :
- 必须包含完善的错误处理逻辑
- 使用try - catch捕获可能的异常
- 对于关键操作 , 添加参数验证
- 错误信息要清晰 , 便于调试
7. * * 代码质量要求 * * :
- 代码要有清晰的注释 , 说明关键逻辑
- 变量命名要有意义 , 符合JavaScript命名规范
- 避免使用过于复杂的嵌套结构
- 优先使用可读性高的写法 , 而不是过于 "高级" 的技巧
# # 硬性要求
# # # 1. 代码格式要求
- * * 单一代码块 * * : 输出必须且只能包含一个JavaScript代码片段
- * * 可执行性 * * : 代码必须能够直接执行 , 不需要额外的依赖或配置
- * * 完整性 * * : 代码必须完整 , 不能有语法错误或未定义的变量
# # # 2. 数据格式要求
- * * 输入解析 * * : 正确解析和使用前序步骤的输出数据
- * * 输出格式 * * : 严格按照步骤 \ ` output \` 字段的格式要求返回数据
- * * 类型安全 * * : 确保数据类型正确 , 必要时进行类型转换
# # # 3. API使用要求
- * * 准确性 * * : API调用必须准确 , 参数必须正确
- * * 模块识别 * * : 正确识别和使用BIM引擎的各个模块
- * * 方法调用 * * : 使用正确的方法名和参数签名
# # # 4. 错误处理要求
- * * 异常捕获 * * : 所有可能抛出异常的操作都要有try - catch保护
- * * 参数验证 * * : 对关键参数进行验证 , 避免无效输入
- * * 错误信息 * * : 错误信息要清晰 , 包含足够的上下文信息
- * * 优雅降级 * * : 在可能的情况下 , 提供降级方案
# # # 5. 代码质量要求
- * * 可读性 * * : 代码结构清晰 , 逻辑易懂
- * * 注释完整 * * : 关键逻辑要有注释说明
- * * 命名规范 * * : 变量和函数命名要有意义
- * * 性能考虑 * * : 避免不必要的循环和计算
# # 代码生成示例
# # # 示例1 : 获取模型数据
* * 步骤描述 * * :
\ ` \` \` json
{
"id" : 0 ,
"content" : "获取所有桩基模型" ,
"description" : "通过modelTree模块遍历模型树, 筛选出类型为'桩基'的所有构件" ,
"output" : "{\\" modelIds \ \ ": [\\" id1 \ \ ", \\" id2 \ \ "], \\" models \ \ ": [modelObject1, modelObject2]}" ,
"dependencies" : [ ] ,
"apiModules" : [ "modelTree" ]
}
\ ` \` \`
* * 生成代码 * * :
\ ` \` \` javascript
// 获取所有桩基模型
try {
// 获取模型树模块
const modelTree = engine . modelTree ;
if ( ! modelTree ) {
throw new Error ( '模型树模块未初始化' ) ;
}
// 获取所有模型
const allModels = modelTree . getAllModels ( ) ;
if ( ! allModels || allModels . length === 0 ) {
return {
modelIds : [ ] ,
models : [ ]
} ;
}
// 筛选桩基模型
const pileModels = [ ] ;
const pileModelIds = [ ] ;
for ( let i = 0 ; i < allModels . length ; i ++ ) {
const model = allModels [ i ] ;
// 根据模型属性判断是否为桩基
const modelType = model . getProperty ( '类型' ) || model . getProperty ( 'category' ) ;
if ( modelType && ( modelType . includes ( '桩基' ) || modelType . includes ( 'Pile' ) ) ) {
pileModels . push ( model ) ;
pileModelIds . push ( model . id || model . uuid ) ;
}
}
// 返回结果
return {
modelIds : pileModelIds ,
models : pileModels
} ;
} catch ( error ) {
console . error ( '获取桩基模型失败:' , error ) ;
return {
modelIds : [ ] ,
models : [ ] ,
error : error . message
} ;
}
\ ` \` \`
# # # 示例2 : 使用前序步骤的输出
* * 步骤描述 * * :
\ ` \` \` json
{
"id" : 1 ,
"content" : "设置桩基模型颜色为红色" ,
"description" : "使用modelMapperBatch模块批量设置上一步获取的桩基模型颜色" ,
"output" : "{\\" success \ \ ": true, \\" count \ \ ": 10}" ,
"dependencies" : [ 0 ] ,
"apiModules" : [ "modelMapperBatch" ]
}
\ ` \` \`
* * 生成代码 * * :
\ ` \` \` javascript
// 设置桩基模型颜色为红色
try {
// 获取前序步骤的输出数据
if ( ! previousStepOutput || ! previousStepOutput . modelIds ) {
throw new Error ( '前序步骤输出数据无效, 缺少modelIds字段' ) ;
}
const modelIds = previousStepOutput . modelIds ;
if ( modelIds . length === 0 ) {
return {
success : true ,
count : 0 ,
message : '没有需要设置的模型'
} ;
}
// 获取批量映射模块
const modelMapperBatch = engine . modelMapperBatch ;
if ( ! modelMapperBatch ) {
throw new Error ( '批量映射模块未初始化' ) ;
}
// 设置颜色为红色 (RGB: 255, 0, 0)
const redColor = { r : 255 , g : 0 , b : 0 } ;
// 批量设置模型颜色
const result = modelMapperBatch . setModelColor ( modelIds , redColor ) ;
return {
success : result . success !== false ,
count : result . count || modelIds . length ,
failedIds : result . failedIds || [ ]
} ;
} catch ( error ) {
console . error ( '设置模型颜色失败:' , error ) ;
return {
success : false ,
count : 0 ,
error : error . message
} ;
}
\ ` \` \`
# # 最佳实践
1. * * 充分理解步骤 * * : 仔细阅读步骤描述 , 确保理解每个细节
2. * * 查阅API文档 * * : 不确定的API用法 , 参考BIM引擎API文档
3. * * 数据验证优先 * * : 在处理数据前 , 先验证数据的有效性
4. * * 错误处理完善 * * : 考虑各种可能的异常情况
5. * * 代码可读性 * * : 优先保证代码的可读性 , 而不是追求 "高级" 写法
6. * * 注释清晰 * * : 关键逻辑要有注释 , 但不要过度注释
7. * * 性能考虑 * * : 对于大量数据的处理 , 考虑性能优化
2026-01-28 18:40:46 +08:00
8. * * 测试友好 * * : 生成的代码应该便于测试和调试 ` },Symbol.toStringTag,{value:"Module"})),bT=Object.freeze(Object.defineProperty({__proto__:null,default: ` # BIM Engine SDK API 文档
2026-01-28 12:00:55 +08:00
本文档为 BIM Engine SDK 的完整 API 参考 , 适合大模型阅读和理解引擎的功能结构 。
# # 目录
1. [ 核心引擎类 ] ( # 1 - 核心引擎类 )
2. [ 基础模块 ] ( # 2 - 基础模块 )
3. [ 功能管理器 ] ( # 3 - 功能管理器 )
4. [ 状态管理 ] ( # 4 - 状态管理 )
-- -
# # 1. 核心引擎类
# # # EngineKernelV2
引擎核心组件 , 负责整合和管理所有模块 。
* * 文件路径 * * : \ ` src/core/v2/EngineKernel.ts \`
# # # # 构造函数
\ ` \` \` typescript
constructor ( options : any )
\ ` \` \`
* * 参数 * * :
- \ ` options.containerId \` : string - 容器元素的 ID
* * 功能 * * :
- 初始化所有基础模块 ( 场景 、 相机 、 渲染器 、 控制器等 )
- 初始化所有功能管理器 ( 测量 、 剖切 、 模型树等 )
- 设置渲染循环
- 添加性能监视器
# # # # 公共属性
\ ` \` \` typescript
// 基础对象
public scene : THREE . Scene | null // 三维场景
public camera : THREE . Camera | null // 当前使用的相机
public renderer : THREE . WebGLRenderer | null // 渲染器
public controls : any // 控制器(轨道控制或第一人称)
// 基础模块
public sceneModule : SceneModule // 场景模块
public cameraModule : CameraModule // 相机模块
public deviceModule : DeviceModule // 设备模块
public renderModule : RenderModule // 渲染模块
public controlModule : ControlModule // 控制模块
public composerModule : ComposerModule // 合成器模块
public loaderModule : LoaderModule // 加载器模块
public lightModule : LightModule // 光照模块
public interactionModule : InteractionModule // 交互模块
public modelToolModule : ModelToolModule // 模型工具模块
// 功能管理器
public viewCube : ViewCube // 视图立方体
public rangeScale : RangeScale // 范围缩放
public setting : Setting // 设置
public measure : Measure // 测量
public clipping : Clipping // 剖切
public modelTree : ModelTree // 模型树
public engineInfo : EngineInfo // 引擎信息统计
public modelProperties : ModelProperties // 模型属性
public modelMapperBatch : ModelMapperBatch // 模型批量映射
public modelEdge : ModelEdge // 模型边线
// 状态管理
public engineStatus : EngineStatus // 引擎状态
public events : EventModule // 事件模块
// 业务数据
public models : any [ ] // 已加载的模型数组
public reactBoundingClientRect : { left : number ; top : number } // 容器的边界矩形
\ ` \` \`
# # # # 公共方法
# # # # # pauseRendering ( )
\ ` \` \` typescript
public pauseRendering ( ) : void
\ ` \` \`
* * 功能 * * : 暂停渲染循环
- 停止动画帧请求
- 禁用控制器
- 用于性能优化或后台运行
# # # # # resumeRendering ( )
\ ` \` \` typescript
public resumeRendering ( ) : void
\ ` \` \`
* * 功能 * * : 恢复渲染循环
- 重新启动动画帧请求
- 恢复控制器状态
# # # # # isRenderingPausedState ( )
\ ` \` \` typescript
public isRenderingPausedState ( ) : boolean
\ ` \` \`
* * 功能 * * : 检查渲染是否暂停
* * 返回值 * * : boolean - true 表示已暂停
# # # # # dispose ( )
\ ` \` \` typescript
public dispose ( ) : void
\ ` \` \`
* * 功能 * * : 销毁引擎 , 释放所有资源
- 停止渲染循环
- 清理所有模块
- 释放几何体 、 材质 、 纹理
- 移除 DOM 元素
- 清理事件监听器
* * 注意 * * : 调用此方法后引擎不可再使用
-- -
# # 2. 基础模块
# # # 2.1 SceneModule - 场景模块
* * 文件路径 * * : \ ` src/core/v2/modules/sceneModule.ts \`
# # # # 公共属性
\ ` \` \` typescript
public scene : THREE . Scene | null // 三维场景对象
\ ` \` \`
* * 功能 * * :
- 创建并管理 THREE . Scene
- 初始化边线组 ( groupEdge ) 用于存储模型边线
-- -
# # # 2.2 CameraModule - 相机模块
* * 文件路径 * * : \ ` src/core/v2/modules/cameraModule.ts \`
# # # # 公共属性
\ ` \` \` typescript
public perspectiveCamera : THREE . PerspectiveCamera // 透视相机
public orthographicCamera : THREE . OrthographicCamera // 正交相机
\ ` \` \`
# # # # 公共方法
# # # # # switchCurrentCamera ( )
\ ` \` \` typescript
public switchCurrentCamera ( ) : void
\ ` \` \`
* * 功能 * * : 切换当前相机类型 ( 透视 ↔ 正交 )
# # # # # switchToPerspectiveCamera ( )
\ ` \` \` typescript
public switchToPerspectiveCamera ( ) : void
\ ` \` \`
* * 功能 * * : 切换到透视相机
- 保持当前位置和目标点
- 更新控制器
- 重新初始化合成器
# # # # # switchToOrthographicCamera ( )
\ ` \` \` typescript
public switchToOrthographicCamera ( ) : void
\ ` \` \`
* * 功能 * * : 切换到正交相机
- 保持当前位置和目标点
- 更新控制器
- 重新初始化合成器
# # # # # getCameraType ( )
\ ` \` \` typescript
public getCameraType ( ) : CameraType
\ ` \` \`
* * 功能 * * : 获取当前相机类型
* * 返回值 * * :
- \ ` CameraType.PERSPECTIVE \` - 透视相机
- \ ` CameraType.ORTHOGRAPHIC \` - 正交相机
# # # # # getCameraPose ( )
\ ` \` \` typescript
public getCameraPose ( ) : ICameraPose
\ ` \` \`
* * 功能 * * : 获取当前相机姿态 ( 位置 、 旋转 、 目标点 、 缩放等 )
* * 返回值 * * : ICameraPose 对象
\ ` \` \` typescript
interface ICameraPose {
type : CameraType ;
position : { x : number ; y : number ; z : number } ;
rotation : { x : number ; y : number ; z : number } ;
quaternion : { x : number ; y : number ; z : number ; w : number } ;
target ? : { x : number ; y : number ; z : number } ;
zoom ? : number ;
}
\ ` \` \`
# # # # # restoreCameraPose ( )
\ ` \` \` typescript
public restoreCameraPose ( pose : ICameraPose ) : void
\ ` \` \`
* * 功能 * * : 通过相机姿态还原相机位置
- 自动切换相机类型
- 恢复位置 、 旋转 、 目标点
- 恢复正交相机的缩放值
* * 参数 * * :
- \ ` pose \` : ICameraPose - 相机姿态对象
-- -
# # # 2.3 DeviceModule - 设备模块
* * 文件路径 * * : \ ` src/core/v2/modules/deviceModule.ts \`
# # # # 公共属性
\ ` \` \` typescript
public deviceType : string // 设备类型(默认 'PC')
\ ` \` \`
# # # # 公共方法
# # # # # getDeviceType ( )
\ ` \` \` typescript
public getDeviceType ( ) : string
\ ` \` \`
* * 功能 * * : 获取设备类型
* * 返回值 * * : 'PC' 或其他设备标识
# # # # # getContainerSize ( )
\ ` \` \` typescript
public getContainerSize ( ) : { width : number ; height : number }
\ ` \` \`
* * 功能 * * : 获取容器尺寸
* * 返回值 * * : 容器的宽度和高度
-- -
# # # 2.4 RenderModule - 渲染模块
* * 文件路径 * * : \ ` src/core/v2/modules/renderModule.ts \`
# # # # 公共属性
\ ` \` \` typescript
public renderer : THREE . WebGLRenderer | null // WebGL 渲染器
\ ` \` \`
# # # # 公共方法
# # # # # createRenderer ( )
\ ` \` \` typescript
public createRenderer ( ) : THREE . WebGLRenderer
\ ` \` \`
* * 功能 * * : 创建并配置 WebGL 渲染器
- 启用抗锯齿
- 启用阴影映射 ( PCFSoftShadowMap )
- 启用本地裁剪 ( 用于剖切平面 )
- 配置色彩空间和色调映射
* * 返回值 * * : 配置好的渲染器实例
# # # # # disposeRenderer ( )
\ ` \` \` typescript
public disposeRenderer ( ) : void
\ ` \` \`
* * 功能 * * : 释放渲染器资源
-- -
# # # 2.5 ControlModule - 控制模块
* * 文件路径 * * : \ ` src/core/v2/modules/controlModule.ts \`
# # # # 公共属性
\ ` \` \` typescript
public orbitControls : any // 轨道控制器
public firstPersonControls : any // 第一人称控制器
public isActive : boolean // 控制器是否激活
\ ` \` \`
# # # # 公共方法
# # # # # init ( )
\ ` \` \` typescript
public init ( ) : void
\ ` \` \`
* * 功能 * * : 初始化控制器
- 创建轨道控制器和第一人称控制器
- 创建旋转中心指示器 UI
# # # # # active ( )
\ ` \` \` typescript
public active ( ) : void
\ ` \` \`
* * 功能 * * : 激活控制器
# # # # # disActive ( )
\ ` \` \` typescript
public disActive ( ) : void
\ ` \` \`
* * 功能 * * : 禁用控制器
# # # # # switchFirstPersonMode ( )
\ ` \` \` typescript
public switchFirstPersonMode ( ) : void
\ ` \` \`
* * 功能 * * : 切换到第一人称漫游模式
- 禁用轨道控制器
- 启用第一人称控制器
# # # # # switchDefaultMode ( )
\ ` \` \` typescript
public switchDefaultMode ( ) : void
\ ` \` \`
* * 功能 * * : 切换到默认模式 ( 轨道控制 )
- 禁用第一人称控制器
- 启用轨道控制器
# # # # # update ( )
\ ` \` \` typescript
public update ( ) : void
\ ` \` \`
* * 功能 * * : 更新控制器状态
- 更新旋转中心指示器位置
- 在渲染循环中调用
-- -
# # # 2.6 ComposerModule - 合成器模块
* * 文件路径 * * : \ ` src/core/v2/modules/composerModule.ts \`
# # # # 公共属性
\ ` \` \` typescript
public composer : any // 效果合成器
\ ` \` \`
# # # # 公共方法
# # # # # init ( )
\ ` \` \` typescript
public init ( ) : void
\ ` \` \`
* * 功能 * * : 初始化后处理管线
- RenderPass - 基础渲染
- GTAOPass - 环境光遮蔽 ( 默认禁用 )
- UnrealBloomPass - 辉光效果 ( 默认禁用 )
- SaturationPass - 饱和度和对比度调整
- OutputPass - 色调映射和颜色校正
- FXAAPass - 抗锯齿
# # # # # resize ( )
\ ` \` \` typescript
public resize ( ) : void
\ ` \` \`
* * 功能 * * : 调整合成器大小
- 更新所有 pass 的分辨率
- 更新 FXAA 的分辨率参数
-- -
# # # 2.7 LoaderModule - 加载器模块
* * 文件路径 * * : \ ` src/core/v2/modules/loaderModule.ts \`
# # # # 公共方法
# # # # # loadModels ( )
\ ` \` \` typescript
async loadModels ( urls : string [ ] , options ? : LoadModelOptions ) : Promise < void >
\ ` \` \`
* * 功能 * * : 加载多个模型
- 支持轻量化模型格式
- 支持 GLTF / GLB 格式
- 异步加载
* * 参数 * * :
- \ ` urls \` : string[] - 模型 URL 数组
- \ ` options \` : LoadModelOptions - 加载选项(可选)
-- -
# # # 2.8 EventModule - 事件模块
* * 文件路径 * * : \ ` src/core/v2/modules/eventModule.ts \`
# # # # 公共方法
# # # # # on ( )
\ ` \` \` typescript
on < T = any > ( event : EventType , callback : ( data : T ) => void ) : void
\ ` \` \`
* * 功能 * * : 注册事件监听器
* * 参数 * * :
- \ ` event \` : EventType - 事件类型
- \ ` callback \` : 回调函数
# # # # # off ( )
\ ` \` \` typescript
off < T = any > ( event : EventType , callback : ( data : T ) => void ) : void
\ ` \` \`
* * 功能 * * : 移除事件监听器
* * 参数 * * :
- \ ` event \` : EventType - 事件类型
- \ ` callback \` : 要移除的回调函数
# # # # # trigger ( )
\ ` \` \` typescript
trigger ( event : EventType , data ? : any ) : void
\ ` \` \`
* * 功能 * * : 触发事件
* * 参数 * * :
- \ ` event \` : EventType - 事件类型
- \ ` data \` : 传递给监听器的数据
* * 常用事件类型 * * :
- \ ` EventType.Click \` - 点击事件
- \ ` EventType.ViewportResize \` - 视口大小改变
- \ ` EventType.EngineFree \` - 引擎空闲
- \ ` EventType.EngineBusy \` - 引擎繁忙
-- -
# # # 2.9 LightModule - 光照模块
* * 文件路径 * * : \ ` src/core/v2/modules/lightModule.ts \`
# # # # 公共方法
# # # # # init ( )
\ ` \` \` typescript
public init ( ) : void
\ ` \` \`
* * 功能 * * : 初始化场景基本光照
- 添加定向光 ( DirectionalLight )
- 强度 : 2
- 位置 : ( 10 , 20 , 10 )
- 阴影贴图 : 4096 x4096 ( 高质量 )
- 添加环境光 ( AmbientLight )
- 强度 : 1
-- -
# # # 2.10 InteractionModule - 交互模块
* * 文件路径 * * : \ ` src/core/v2/modules/interactionModule.ts \`
# # # # 公共方法
# # # # # init ( )
\ ` \` \` typescript
public init ( ) : void
\ ` \` \`
* * 功能 * * : 初始化交互行为处理器
# # # # # active ( )
\ ` \` \` typescript
public active ( ) : void
\ ` \` \`
* * 功能 * * : 激活交互功能
# # # # # disActive ( )
\ ` \` \` typescript
public disActive ( ) : void
\ ` \` \`
* * 功能 * * : 禁用交互功能
# # # # # handleMouseClick ( )
\ ` \` \` typescript
public handleMouseClick ( event : any ) : void
\ ` \` \`
* * 功能 * * : 处理鼠标单击事件
- 射线检测点击的模型
- 高亮选中的模型
- 设置旋转中心
- 支持 Ctrl 多选
# # # # # handleMouseDoubleClick ( )
\ ` \` \` typescript
public handleMouseDoubleClick ( event : any ) : void
\ ` \` \`
* * 功能 * * : 处理鼠标双击事件
- 双击模型后缩放到该模型
- 计算模型包围盒并调整相机视角
# # # # # handleMouseClickInstance ( )
\ ` \` \` typescript
public handleMouseClickInstance ( raycaster : any ) : any
\ ` \` \`
* * 功能 * * : 判断点击实例化网格节点
* * 参数 * * :
- \ ` raycaster \` : 射线投射器
* * 返回值 * * : 相交结果数组
-- -
# # # 2.11 ModelToolModule - 模型工具模块
* * 文件路径 * * : \ ` src/core/v2/modules/modelToolModule.ts \`
# # # # 公共方法
# # # # # highlightModel ( )
\ ` \` \` typescript
public highlightModel ( models : any ) : void
\ ` \` \`
* * 功能 * * : 设置模型高亮显示
* * 参数 * * :
- \ ` models \` : 模型数组,格式: \` [{url: string, ids: string[]}] \`
# # # # # unhighlightModel ( )
\ ` \` \` typescript
public unhighlightModel ( models : any ) : void
\ ` \` \`
* * 功能 * * : 取消模型高亮
* * 参数 * * :
- \ ` models \` : 模型数组
# # # # # unhighlightAllModels ( )
\ ` \` \` typescript
public unhighlightAllModels ( ) : void
\ ` \` \`
* * 功能 * * : 取消所有模型高亮
# # # # # hideModel ( )
\ ` \` \` typescript
public hideModel ( models : any ) : void
\ ` \` \`
* * 功能 * * : 隐藏模型
* * 参数 * * :
- \ ` models \` : 模型数组,格式: \` [{url: string, ids: string[]}] \`
# # # # # showModel ( )
\ ` \` \` typescript
public showModel ( models : any ) : void
\ ` \` \`
* * 功能 * * : 显示模型
* * 参数 * * :
- \ ` models \` : 模型数组
# # # # # isolateModel ( )
\ ` \` \` typescript
public isolateModel ( models : any ) : void
\ ` \` \`
* * 功能 * * : 隔离模型 ( 只显示指定模型 , 隐藏其他 )
* * 参数 * * :
- \ ` models \` : 要显示的模型数组
# # # # # showAllModels ( )
\ ` \` \` typescript
public showAllModels ( ) : void
\ ` \` \`
* * 功能 * * : 显示所有模型
# # # # # getModelsBox ( )
\ ` \` \` typescript
public getModelsBox ( models : any ) : THREE . Box3
\ ` \` \`
* * 功能 * * : 获取模型的包围盒
* * 参数 * * :
- \ ` models \` : 模型数组
* * 返回值 * * : THREE . Box3 包围盒对象
-- -
# # 3. 功能管理器
# # # 3.1 ViewCube - 视图立方体
* * 文件路径 * * : \ ` src/core/v2/managers/viewCube/index.ts \`
# # # # 公共属性
\ ` \` \` typescript
public cubeTool : any // 视图立方体工具
\ ` \` \`
# # # # 公共方法
# # # # # init ( )
\ ` \` \` typescript
public init ( ) : void
\ ` \` \`
* * 功能 * * : 初始化视图立方体
- 创建 3 D 小立方体辅助视图
- 支持六个面和边角视图切换
# # # # # CameraGoHome ( )
\ ` \` \` typescript
public CameraGoHome ( ) : void
\ ` \` \`
* * 功能 * * : 相机回归正位 ( 默认视角 )
# # # # # zoomToModel ( )
\ ` \` \` typescript
public zoomToModel ( box : THREE . Box3 ) : void
\ ` \` \`
* * 功能 * * : 缩放到指定模型包围盒
* * 参数 * * :
- \ ` box \` : THREE.Box3 - 目标包围盒
-- -
# # # 3.2 RangeScale - 范围缩放工具
* * 文件路径 * * : \ ` src/core/v2/managers/rangeScale/index.ts \`
# # # # 公共方法
# # # # # init ( )
\ ` \` \` typescript
public init ( ) : void
\ ` \` \`
* * 功能 * * : 初始化范围缩放工具
- 创建绘制框 UI 元素
- 初始化坐标转换工具
# # # # # active ( )
\ ` \` \` typescript
public active ( ) : void
\ ` \` \`
* * 功能 * * : 激活范围缩放工具
- 禁用控制器
- 启用框选功能
- 鼠标变为十字光标
* * 使用方式 * * :
1. 激活工具
2. 鼠标拖拽绘制矩形区域
3. 松开鼠标自动缩放到该区域
4. 按 ESC 键退出
# # # # # disActive ( )
\ ` \` \` typescript
public disActive ( ) : void
\ ` \` \`
* * 功能 * * : 停用范围缩放工具
- 恢复控制器
- 移除事件监听
-- -
# # # 3.3 Setting - 设置管理器
* * 文件路径 * * : \ ` src/core/v2/managers/setting/index.ts \`
# # # # 公共方法
# # # # # setStatsVisible ( )
\ ` \` \` typescript
public setStatsVisible ( visible : boolean ) : void
\ ` \` \`
* * 功能 * * : 显示 / 隐藏性能监视器
* * 参数 * * :
- \ ` visible \` : true 显示, false 隐藏
# # # # # setAmbientLightIntensity ( )
\ ` \` \` typescript
public setAmbientLightIntensity ( intensity : number ) : void
\ ` \` \`
* * 功能 * * : 设置环境光照强度
* * 参数 * * :
- \ ` intensity \` : 光照强度,范围 0-5
# # # # # setAmbientLightColor ( )
\ ` \` \` typescript
public setAmbientLightColor ( color : number | string ) : void
\ ` \` \`
* * 功能 * * : 设置环境光照颜色
* * 参数 * * :
- \ ` color \` : 颜色( 0xffffff 或 '#ffffff')
# # # # # setDirectionalLightIntensity ( )
\ ` \` \` typescript
public setDirectionalLightIntensity ( intensity : number ) : void
\ ` \` \`
* * 功能 * * : 设置定向光源强度
* * 参数 * * :
- \ ` intensity \` : 光照强度,范围 0-5
# # # # # setDirectionalLightColor ( )
\ ` \` \` typescript
public setDirectionalLightColor ( color : number | string ) : void
\ ` \` \`
* * 功能 * * : 设置定向光源颜色
* * 参数 * * :
- \ ` color \` : 颜色
# # # # # setShadowQuality ( )
\ ` \` \` typescript
public setShadowQuality ( quality : 'low' | 'medium' | 'high' | 'ultra' ) : void
\ ` \` \`
* * 功能 * * : 设置阴影精细度
* * 参数 * * :
- \ ` quality \` : 质量等级
- 'low' : 1024
- 'medium' : 2048
- 'high' : 4096
- 'ultra' : 8192
# # # # # setDirectionalLightShadow ( )
\ ` \` \` typescript
public setDirectionalLightShadow ( enabled : boolean ) : void
\ ` \` \`
* * 功能 * * : 开启 / 关闭定向光阴影
* * 参数 * * :
- \ ` enabled \` : true 开启, false 关闭
# # # # # setGTAOEnabled ( )
\ ` \` \` typescript
public setGTAOEnabled ( enabled : boolean ) : void
\ ` \` \`
* * 功能 * * : 开启 / 关闭 GTAO 环境光遮蔽
* * 参数 * * :
- \ ` enabled \` : true 开启, false 关闭
# # # # # setSceneSaturation ( )
\ ` \` \` typescript
public setSceneSaturation ( saturation : number ) : void
\ ` \` \`
* * 功能 * * : 设置场景饱和度
* * 参数 * * :
- \ ` saturation \` : 饱和度值, 1.0 为正常,推荐范围 0.5-2.0
# # # # # setSceneContrast ( )
\ ` \` \` typescript
public setSceneContrast ( contrast : number ) : void
\ ` \` \`
* * 功能 * * : 设置场景对比度
* * 参数 * * :
- \ ` contrast \` : 对比度值, 1.0 为正常,推荐范围 0.5-2.0
# # # # # setGroundEnabled ( )
\ ` \` \` typescript
public setGroundEnabled ( enabled : boolean , options ? : {
size ? : number ;
color ? : number | string ;
opacity ? : number ;
} ) : void
\ ` \` \`
* * 功能 * * : 开启 / 关闭地面
* * 参数 * * :
- \ ` enabled \` : true 开启, false 关闭
- \ ` options \` : 地面配置选项
- \ ` size \` : 地面大小(默认 100)
- \ ` color \` : 地面颜色(默认 0x808080)
- \ ` opacity \` : 透明度(默认 0.3)
# # # # # setHDRBackground ( )
\ ` \` \` typescript
public setHDRBackground ( hdrTexture : THREE . Texture | null ) : void
\ ` \` \`
* * 功能 * * : 设置 HDR 背景
* * 参数 * * :
- \ ` hdrTexture \` : HDR 环境贴图, null 则移除
-- -
# # # 3.4 Measure - 测量工具
* * 文件路径 * * : \ ` src/core/v2/managers/measure/index.ts \`
# # # # 公共方法
# # # # # active ( )
\ ` \` \` typescript
public active ( ) : void
\ ` \` \`
* * 功能 * * : 激活测量工具
# # # # # disActive ( )
\ ` \` \` typescript
public disActive ( ) : void
\ ` \` \`
* * 功能 * * : 停用测量工具
- 清除所有测量
- 恢复点选功能
# # # # # clearAllPoints ( )
\ ` \` \` typescript
public clearAllPoints ( ) : void
\ ` \` \`
* * 功能 * * : 清空所有测量点
# # # # # clearAll ( )
\ ` \` \` typescript
public clearAll ( ) : void
\ ` \` \`
* * 功能 * * : 清除所有测量标注
# # # # # update ( )
\ ` \` \` typescript
update ( ) : void
\ ` \` \`
* * 功能 * * : 更新测量标注
- 在渲染循环中调用
- 更新屏幕坐标
* * 测量类型 * * :
- 距离测量 ( DistanceMeasure )
- 净高测量 ( ClearHeightMeasure )
- 净距测量 ( ClearDistanceMeasure )
- 标高测量 ( ElevationMeasure )
- 点测量 ( PointMeasure )
- 角度测量 ( AngleMeasure )
- 面积测量 ( AreaMeasure )
- 坡度测量 ( SlopeMeasure )
-- -
# # # 3.5 Clipping - 剖切管理器
* * 文件路径 * * : \ ` src/core/v2/managers/clipping/index.ts \`
# # # # 公共属性
\ ` \` \` typescript
public sectionPlaneX : any // X 轴剖切平面
public sectionPlaneY : any // Y 轴剖切平面
public sectionPlaneZ : any // Z 轴剖切平面
public sectionBox : any // 剖切盒
\ ` \` \`
# # # # 公共方法
# # # # # init ( )
\ ` \` \` typescript
public init ( ) : void
\ ` \` \`
* * 功能 * * : 初始化剖切管理器
- 创建 6 个剖切平面 ( 前 、 后 、 左 、 右 、 顶 、 底 )
- 初始化 X / Y / Z 轴剖切工具
- 初始化剖切盒工具
# # # # # disActive ( )
\ ` \` \` typescript
public disActive ( ) : void
\ ` \` \`
* * 功能 * * : 停用所有剖切工具
-- -
# # # 3.6 ModelTree - 模型树
* * 文件路径 * * : \ ` src/core/v2/managers/modelTree/index.ts \`
# # # # 公共方法
# # # # # getTreeData ( )
\ ` \` \` typescript
public getTreeData ( ) : any [ ]
\ ` \` \`
* * 功能 * * : 获取模型树数据
* * 返回值 * * : 模型树数组
\ ` \` \` typescript
[ {
name : string , // 模型名称
children : any [ ] // 模型层级树
} ]
\ ` \` \`
-- -
# # # 3.7 EngineInfo - 引擎信息统计
* * 文件路径 * * : \ ` src/core/v2/managers/engineInfo/index.ts \`
# # # # 公共方法
# # # # # getEngineInfo ( )
\ ` \` \` typescript
public getEngineInfo ( ) : {
totalVertices : number ;
totalTriangles : number ;
meshCount : number ;
}
\ ` \` \`
* * 功能 * * : 获取引擎统计信息
- 统计所有网格的顶点数
- 统计所有网格的三角面数
- 统计网格数量
* * 返回值 * * :
- \ ` totalVertices \` : 总顶点数
- \ ` totalTriangles \` : 总三角面数
- \ ` meshCount \` : 网格数量
-- -
# # # 3.8 ModelProperties - 模型属性
* * 文件路径 * * : \ ` src/core/v2/managers/modelProperties/index.ts \`
# # # # 公共方法
# # # # # getModelProperties ( )
\ ` \` \` typescript
public getModelProperties ( url : string , id : string , callback : ( properties : any ) => void ) : void
\ ` \` \`
* * 功能 * * : 查询构件属性
- 异步加载属性数据 ( 如果未加载 )
- 从压缩的 JSON 中解析属性
* * 参数 * * :
- \ ` url \` : 模型 URL
- \ ` id \` : 构件 ID
- \ ` callback \` : 回调函数,接收属性对象
* * 返回值格式 * * :
\ ` \` \` typescript
{
properties : [ {
name : string , // 分类名称
children : [ {
name : string , // 属性名
value : any // 属性值
} ]
} ] ,
materials : [ ]
}
\ ` \` \`
-- -
# # # 3.9 ModelMapperBatch - 模型批量映射
* * 文件路径 * * : \ ` src/core/v2/managers/modelMapperBatch/index.ts \`
# # # # 公共方法
# # # # # getModelTypes ( )
\ ` \` \` typescript
public getModelTypes ( ) : any [ ]
\ ` \` \`
* * 功能 * * : 获取模型中所有的构件类型
# # # # # getModelMajors ( )
\ ` \` \` typescript
public getModelMajors ( ) : any [ ]
\ ` \` \`
* * 功能 * * : 获取模型中所有的专业
# # # # # getModelLevels ( )
\ ` \` \` typescript
public getModelLevels ( ) : any [ ]
\ ` \` \`
* * 功能 * * : 获取模型中所有的楼层
# # # # # getModelMapper ( )
\ ` \` \` typescript
public getModelMapper ( url : string , id : number ) : any
\ ` \` \`
* * 功能 * * : 获取指定构件的映射信息
* * 参数 * * :
- \ ` url \` : 模型 URL
- \ ` id \` : 构件 ID
* * 返回值 * * : Mapper 对象 ( 包含类型 、 专业 、 楼层等信息 )
# # # # # getModelSWithType ( )
\ ` \` \` typescript
public getModelSWithType ( type : string , callback : any ) : any [ ]
\ ` \` \`
* * 功能 * * : 获取同类型的所有构件
* * 参数 * * :
- \ ` type \` : 构件类型名称
- \ ` callback \` : 回调函数
* * 返回值 * * : \ ` [{url: string, ids: number[]}] \`
# # # # # getModelSWithLevel ( )
\ ` \` \` typescript
public getModelSWithLevel ( level : string , callback : any ) : any [ ]
\ ` \` \`
* * 功能 * * : 获取同楼层的所有构件
* * 参数 * * :
- \ ` level \` : 楼层名称
- \ ` callback \` : 回调函数
* * 返回值 * * : \ ` [{url: string, ids: number[]}] \`
# # # # # getModelsWithMajor ( )
\ ` \` \` typescript
public getModelsWithMajor ( major : string , callback : any ) : any [ ]
\ ` \` \`
* * 功能 * * : 获取同专业的所有构件
* * 参数 * * :
- \ ` major \` : 专业名称
- \ ` callback \` : 回调函数
* * 返回值 * * : \ ` [{url: string, ids: number[]}] \`
-- -
# # # 3.10 ModelEdge - 模型边线管理器
* * 文件路径 * * : \ ` src/core/v2/managers/modelEdge/index.ts \`
# # # # 公共方法
# # # # # active ( )
\ ` \` \` typescript
public active ( ) : void
\ ` \` \`
* * 功能 * * : 启动边线显示
- 显示所有模型的边线
- 用于技术制图风格渲染
# # # # # disActive ( )
\ ` \` \` typescript
public disActive ( ) : void
\ ` \` \`
* * 功能 * * : 关闭边线显示
# # # # # getModelEdge ( )
\ ` \` \` typescript
public getModelEdge ( url : string , id : Number ) : any
\ ` \` \`
* * 功能 * * : 获取指定模型的边线数据
* * 参数 * * :
- \ ` url \` : 模型 URL
- \ ` id \` : 构件 ID
* * 返回值 * * : 边线数据 \ ` [startIndex, endIndex, points] \`
# # # # # hideModelEdge ( )
\ ` \` \` typescript
public hideModelEdge ( url : string , id : Number ) : void
\ ` \` \`
* * 功能 * * : 隐藏指定构件的边线
* * 参数 * * :
- \ ` url \` : 模型 URL
- \ ` id \` : 构件 ID
# # # # # showModelEdge ( )
\ ` \` \` typescript
public showModelEdge ( url : string , id : Number ) : void
\ ` \` \`
* * 功能 * * : 显示指定构件的边线
* * 参数 * * :
- \ ` url \` : 模型 URL
- \ ` id \` : 构件 ID
-- -
# # 4. 状态管理
# # # 4.1 EngineStatus - 引擎状态
* * 文件路径 * * : \ ` src/core/v2/status/engineStatus.ts \`
# # # # 公共属性
\ ` \` \` typescript
public isFree : boolean // 引擎是否空闲
public highlightModels : any [ ] // 高亮的模型数组
public hideModels : any [ ] // 隐藏的模型数组
public models : any [ ] // 已加载的模型数组
\ ` \` \`
# # # # 公共方法
# # # # # init ( )
\ ` \` \` typescript
public init ( ) : void
\ ` \` \`
* * 功能 * * : 初始化引擎状态监听
- 监听 \ ` EventType.EngineFree \` 事件
- 监听 \ ` EventType.EngineBusy \` 事件
# # # # # updateFree ( )
\ ` \` \` typescript
public updateFree ( status : boolean ) : void
\ ` \` \`
* * 功能 * * : 更新引擎空闲状态
* * 参数 * * :
- \ ` status \` : true 表示空闲, false 表示繁忙
# # # # # closeAllFunction ( )
\ ` \` \` typescript
public closeAllFunction ( ) : void
\ ` \` \`
* * 功能 * * : 关闭所有功能
-- -
# # # 4.2 HandelBehaved - 行为处理器
* * 文件路径 * * : \ ` src/core/v2/status/handelBehaved.ts \`
这是一个工厂函数 , 返回行为处理器对象 。
# # # # 公共方法
# # # # # init ( )
\ ` \` \` typescript
init ( self : any , options : any ) : void
\ ` \` \`
* * 功能 * * : 初始化行为处理器
* * 参数 * * :
- \ ` self \` : 当前激活的行为对象
- \ ` options \` : 行为配置选项
- \ ` showCatch \` : boolean - 是否显示捕捉点
# # # # # active ( )
\ ` \` \` typescript
active ( ) : void
\ ` \` \`
* * 功能 * * : 开启事务 ( 激活事件监听 )
- 监听鼠标事件 ( mousedown , mouseup , mousemove )
- 监听键盘事件 ( keydown , keyup )
# # # # # disActive ( )
\ ` \` \` typescript
disActive ( ) : void
\ ` \` \`
* * 功能 * * : 关闭事务 ( 禁用事件监听 )
* * 支持的键盘事件 * * :
- Delete / Backspace - 删除
- Escape - 取消
- Enter - 确认
- Space - 空格
- Ctrl / Control - 控制键
- Shift - 切换键
- Alt - 辅助键
- Meta / Command - 命令键
* * 支持的鼠标事件 * * :
- handleMouseDown - 鼠标按下
- handleMouseMove - 鼠标移动
- handleMouseUp - 鼠标弹起
- handleMouseClick - 鼠标单击
- handleMouseDoubleClick - 鼠标双击
* * 捕捉功能 * * :
- 点捕捉 ( 距离 < 5 像素 )
- 线捕捉 ( 距离 < 5 像素 )
- 面捕捉 ( 默认 )
-- -
# # 使用示例
# # # 初始化引擎
\ ` \` \` typescript
import { EngineKernelV2 } from './src/core/v2/EngineKernel' ;
const engine = new EngineKernelV2 ( {
containerId : 'canvas-container' ,
antialias : true
} ) ;
\ ` \` \`
# # # 加载模型
\ ` \` \` typescript
await engine . loaderModule . loadModels ( [
'https://example.com/model1.light' ,
'https://example.com/model2.light'
] ) ;
\ ` \` \`
# # # 高亮模型
\ ` \` \` typescript
engine . modelToolModule . highlightModel ( [
{ url : 'model1.light' , ids : [ 'wall-001' , 'wall-002' ] }
] ) ;
\ ` \` \`
# # # 切换相机
\ ` \` \` typescript
// 切换到正交相机
engine . cameraModule . switchToOrthographicCamera ( ) ;
// 或切换当前相机类型
engine . cameraModule . switchCurrentCamera ( ) ;
\ ` \` \`
# # # 保存和恢复相机姿态
\ ` \` \` typescript
// 保存当前相机姿态
const pose = engine . cameraModule . getCameraPose ( ) ;
// 恢复相机姿态
engine . cameraModule . restoreCameraPose ( pose ) ;
\ ` \` \`
# # # 设置光照和渲染质量
\ ` \` \` typescript
// 设置环境光强度
engine . setting . setAmbientLightIntensity ( 1.5 ) ;
// 设置阴影质量
engine . setting . setShadowQuality ( 'ultra' ) ;
// 开启 GTAO
engine . setting . setGTAOEnabled ( true ) ;
// 调整饱和度和对比度
engine . setting . setSceneSaturation ( 1.3 ) ;
engine . setting . setSceneContrast ( 1.1 ) ;
\ ` \` \`
# # # 获取模型属性
\ ` \` \` typescript
engine . modelProperties . getModelProperties ( 'model.light' , 'wall-001' , ( data ) => {
console . log ( '属性:' , data . properties ) ;
} ) ;
\ ` \` \`
# # # 按类型筛选构件
\ ` \` \` typescript
engine . modelMapperBatch . getModelSWithType ( '墙' , ( models ) => {
// 高亮所有墙体
engine . modelToolModule . highlightModel ( models ) ;
} ) ;
\ ` \` \`
# # # 监听事件
\ ` \` \` typescript
// 监听点击事件
engine . events . on ( EventType . Click , ( hit ) => {
console . log ( '点击了:' , hit . object . name ) ;
} ) ;
// 监听视口大小改变
engine . events . on ( EventType . ViewportResize , ( { width , height } ) => {
console . log ( '视口大小:' , width , height ) ;
} ) ;
\ ` \` \`
# # # 暂停和恢复渲染
\ ` \` \` typescript
// 暂停渲染(节省性能)
engine . pauseRendering ( ) ;
// 恢复渲染
engine . resumeRendering ( ) ;
// 检查渲染状态
if ( engine . isRenderingPausedState ( ) ) {
console . log ( '渲染已暂停' ) ;
}
\ ` \` \`
# # # 销毁引擎
\ ` \` \` typescript
// 释放所有资源
engine . dispose ( ) ;
\ ` \` \`
-- -
# # 总结
BIM Engine SDK 提供了完整的 3 D BIM 模型渲染和交互能力 , 主要特性包括 :
- * * 完整的相机系统 * * : 支持透视和正交相机 , 可保存和恢复相机姿态
- * * 强大的模型操作 * * : 高亮 、 隐藏 、 隔离 、 批量筛选
- * * 丰富的测量工具 * * : 距离 、 净高 、 净距 、 标高 、 角度 、 面积 、 坡度
- * * 灵活的剖切功能 * * : 支持 X / Y / Z 轴剖切和剖切盒
- * * 可配置的渲染质量 * * : 阴影 、 环境光遮蔽 、 饱和度 、 对比度
- * * 事件驱动架构 * * : 支持自定义事件监听和触发
- * * 性能优化 * * : 支持暂停 / 恢复渲染 , 八叉树加速
- * * 完善的资源管理 * * : 自动释放几何体 、 材质 、 纹理等资源
适用场景 :
- BIM 模型在线浏览
- 建筑设计审查
- 施工模拟
- 运维管理
- AI 辅助设计
2026-01-28 18:40:46 +08:00
` },Symbol.toStringTag,{value:"Module"}));Bs.BimEngine=sT,Object.defineProperty(Bs,Symbol.toStringTag,{value:"Module"})}));
2026-01-22 11:29:51 +08:00
//# sourceMappingURL=iflow-engine.umd.js.map