SSRrShader.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. ( function () {
  2. const SSRrShader = {
  3. defines: {
  4. MAX_STEP: 0,
  5. PERSPECTIVE_CAMERA: true,
  6. SPECULAR: true,
  7. FILL_HOLE: true,
  8. INFINITE_THICK: false
  9. },
  10. uniforms: {
  11. 'tDiffuse': {
  12. value: null
  13. },
  14. 'tSpecular': {
  15. value: null
  16. },
  17. 'tNormalSelects': {
  18. value: null
  19. },
  20. 'tRefractive': {
  21. value: null
  22. },
  23. 'tDepth': {
  24. value: null
  25. },
  26. 'tDepthSelects': {
  27. value: null
  28. },
  29. 'cameraNear': {
  30. value: null
  31. },
  32. 'cameraFar': {
  33. value: null
  34. },
  35. 'resolution': {
  36. value: new THREE.Vector2()
  37. },
  38. 'cameraProjectionMatrix': {
  39. value: new THREE.Matrix4()
  40. },
  41. 'cameraInverseProjectionMatrix': {
  42. value: new THREE.Matrix4()
  43. },
  44. 'ior': {
  45. value: 1.03
  46. },
  47. 'cameraRange': {
  48. value: 0
  49. },
  50. 'maxDistance': {
  51. value: 180
  52. },
  53. 'surfDist': {
  54. value: .007
  55. }
  56. },
  57. vertexShader:
  58. /* glsl */
  59. `
  60. varying vec2 vUv;
  61. void main() {
  62. vUv = uv;
  63. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  64. }
  65. `,
  66. fragmentShader:
  67. /* glsl */
  68. `
  69. // precision highp float;
  70. precision highp sampler2D;
  71. varying vec2 vUv;
  72. uniform sampler2D tDepth;
  73. uniform sampler2D tDepthSelects;
  74. uniform sampler2D tNormalSelects;
  75. uniform sampler2D tRefractive;
  76. uniform sampler2D tDiffuse;
  77. uniform sampler2D tSpecular;
  78. uniform float cameraRange;
  79. uniform vec2 resolution;
  80. uniform float cameraNear;
  81. uniform float cameraFar;
  82. uniform float ior;
  83. uniform mat4 cameraProjectionMatrix;
  84. uniform mat4 cameraInverseProjectionMatrix;
  85. uniform float maxDistance;
  86. uniform float surfDist;
  87. #include <packing>
  88. float pointToLineDistance(vec3 x0, vec3 x1, vec3 x2) {
  89. //x0: point, x1: linePointA, x2: linePointB
  90. //https://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
  91. return length(cross(x0-x1,x0-x2))/length(x2-x1);
  92. }
  93. float pointPlaneDistance(vec3 point,vec3 planePoint,vec3 planeNormal){
  94. // https://mathworld.wolfram.com/Point-PlaneDistance.html
  95. //// https://en.wikipedia.org/wiki/Plane_(geometry)
  96. //// http://paulbourke.net/geometry/pointlineplane/
  97. float a=planeNormal.x,b=planeNormal.y,c=planeNormal.z;
  98. float x0=point.x,y0=point.y,z0=point.z;
  99. float x=planePoint.x,y=planePoint.y,z=planePoint.z;
  100. float d=-(a*x+b*y+c*z);
  101. float distance=(a*x0+b*y0+c*z0+d)/sqrt(a*a+b*b+c*c);
  102. return distance;
  103. }
  104. float getDepth( const in vec2 uv ) {
  105. return texture2D( tDepth, uv ).x;
  106. }
  107. float getDepthSelects( const in vec2 uv ) {
  108. return texture2D( tDepthSelects, uv ).x;
  109. }
  110. float getViewZ( const in float depth ) {
  111. #ifdef PERSPECTIVE_CAMERA
  112. return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );
  113. #else
  114. return orthographicDepthToViewZ( depth, cameraNear, cameraFar );
  115. #endif
  116. }
  117. vec3 getViewPosition( const in vec2 uv, const in float depth/*clip space*/, const in float clipW ) {
  118. vec4 clipPosition = vec4( ( vec3( uv, depth ) - 0.5 ) * 2.0, 1.0 );//ndc
  119. clipPosition *= clipW; //clip
  120. return ( cameraInverseProjectionMatrix * clipPosition ).xyz;//view
  121. }
  122. vec3 getViewNormalSelects( const in vec2 uv ) {
  123. return unpackRGBToNormal( texture2D( tNormalSelects, uv ).xyz );
  124. }
  125. vec2 viewPositionToXY(vec3 viewPosition){
  126. vec2 xy;
  127. vec4 clip=cameraProjectionMatrix*vec4(viewPosition,1);
  128. xy=clip.xy;//clip
  129. float clipW=clip.w;
  130. xy/=clipW;//NDC
  131. xy=(xy+1.)/2.;//uv
  132. xy*=resolution;//screen
  133. return xy;
  134. }
  135. void setResultColor(vec2 uv){
  136. vec4 refractColor=texture2D(tDiffuse,uv);
  137. #ifdef SPECULAR
  138. vec4 specularColor=texture2D(tSpecular,vUv);
  139. gl_FragColor.xyz=mix(refractColor.xyz,vec3(1),specularColor.r);
  140. // gl_FragColor.xyz=refractColor.xyz*(1.+specularColor.r*3.);
  141. #else
  142. gl_FragColor.xyz=refractColor.xyz;
  143. #endif
  144. gl_FragColor.a=1.;
  145. }
  146. void main(){
  147. if(ior==1.) return; // Adding this line may have better performance, but more importantly, it can avoid display errors at the very edges of the model when IOR is equal to 1.
  148. float refractive=texture2D(tRefractive,vUv).r;
  149. if(refractive<=0.) return;
  150. // gl_FragColor=vec4(0,0,.5,1);return;
  151. vec3 viewNormalSelects=getViewNormalSelects( vUv );
  152. // gl_FragColor=vec4(viewNormalSelects,1);return;
  153. // if(viewNormalSelects.x<=0.&&viewNormalSelects.y<=0.&&viewNormalSelects.z<=0.) return;
  154. float depth = getDepthSelects( vUv );
  155. float viewZ = getViewZ( depth );
  156. // if(-viewZ>=cameraFar) return;
  157. float clipW = cameraProjectionMatrix[2][3] * viewZ+cameraProjectionMatrix[3][3];
  158. vec3 viewPosition=getViewPosition( vUv, depth, clipW );
  159. vec2 d0=gl_FragCoord.xy;
  160. vec2 d1;
  161. #ifdef PERSPECTIVE_CAMERA
  162. vec3 viewIncidentDir=normalize(viewPosition);
  163. #else
  164. vec3 viewIncidentDir=vec3(0,0,-1);
  165. #endif
  166. vec3 viewRefractDir=refract(viewIncidentDir,viewNormalSelects,1./ior);
  167. // https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/refract.xhtml
  168. vec3 d1viewPosition=viewPosition+viewRefractDir*maxDistance;
  169. #ifdef PERSPECTIVE_CAMERA
  170. if(d1viewPosition.z>-cameraNear){
  171. //https://tutorial.math.lamar.edu/Classes/CalcIII/EqnsOfLines.aspx
  172. float t=(-cameraNear-viewPosition.z)/viewRefractDir.z;
  173. d1viewPosition=viewPosition+viewRefractDir*t;
  174. }
  175. #endif
  176. d1=viewPositionToXY(d1viewPosition);
  177. float totalLen=length(d1-d0);
  178. float xLen=d1.x-d0.x;
  179. float yLen=d1.y-d0.y;
  180. float totalStep=max(abs(xLen),abs(yLen));
  181. float xSpan=xLen/totalStep;
  182. float ySpan=yLen/totalStep;
  183. #ifdef FILL_HOLE
  184. bool isRough=false;
  185. vec2 uvRough;
  186. #endif
  187. for(float i=0.;i<float(MAX_STEP);i++){
  188. if(i>=totalStep) break;
  189. vec2 xy=vec2(d0.x+i*xSpan,d0.y+i*ySpan);
  190. if(xy.x<0.||xy.x>resolution.x||xy.y<0.||xy.y>resolution.y) break;
  191. float s=length(xy-d0)/totalLen;
  192. vec2 uv=xy/resolution;
  193. float d = getDepth(uv);
  194. float vZ = getViewZ( d );
  195. float cW = cameraProjectionMatrix[2][3] * vZ+cameraProjectionMatrix[3][3];
  196. vec3 vP=getViewPosition( uv, d, cW );
  197. #ifdef PERSPECTIVE_CAMERA
  198. // https://www.comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf
  199. float recipVPZ=1./viewPosition.z;
  200. float viewRefractRayZ=1./(recipVPZ+s*(1./d1viewPosition.z-recipVPZ));
  201. float sD=surfDist*cW;
  202. #else
  203. float viewRefractRayZ=viewPosition.z+s*(d1viewPosition.z-viewPosition.z);
  204. float sD=surfDist;
  205. #endif
  206. #ifdef FILL_HOLE // TODO: May can improve performance by check if INFINITE_THICK too.
  207. if(viewRefractRayZ<=vZ){
  208. if(!isRough){
  209. uvRough=uv;
  210. isRough=true;
  211. }
  212. }
  213. #endif
  214. bool hit;
  215. #ifdef INFINITE_THICK
  216. hit=viewRefractRayZ<=vZ;
  217. #else
  218. if(viewRefractRayZ-sD>vZ) continue;
  219. float away=pointToLineDistance(vP,viewPosition,d1viewPosition);
  220. hit=away<=sD;
  221. #endif
  222. if(hit){
  223. setResultColor(uv);
  224. return;
  225. }
  226. }
  227. #ifdef FILL_HOLE
  228. if(isRough){
  229. setResultColor(uvRough);
  230. }
  231. // else{
  232. // gl_FragColor=texture2D(tDiffuse,vUv);//For afterward add color mix feature.
  233. // }
  234. #else
  235. // gl_FragColor=texture2D(tDiffuse,vUv);//For afterward add color mix feature.
  236. #endif
  237. }
  238. `
  239. };
  240. var SSRrDepthShader = {
  241. defines: {
  242. 'PERSPECTIVE_CAMERA': 1
  243. },
  244. uniforms: {
  245. 'tDepth': {
  246. value: null
  247. },
  248. 'cameraNear': {
  249. value: null
  250. },
  251. 'cameraFar': {
  252. value: null
  253. }
  254. },
  255. vertexShader:
  256. /* glsl */
  257. `
  258. varying vec2 vUv;
  259. void main() {
  260. vUv = uv;
  261. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  262. }
  263. `,
  264. fragmentShader:
  265. /* glsl */
  266. `
  267. uniform sampler2D tDepth;
  268. uniform float cameraNear;
  269. uniform float cameraFar;
  270. varying vec2 vUv;
  271. #include <packing>
  272. float getLinearDepth( const in vec2 uv ) {
  273. #if PERSPECTIVE_CAMERA == 1
  274. float fragCoordZ = texture2D( tDepth, uv ).x;
  275. float viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );
  276. return viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );
  277. #else
  278. return texture2D( tDepth, uv ).x;
  279. #endif
  280. }
  281. void main() {
  282. float depth = getLinearDepth( vUv );
  283. float d = 1.0 - depth;
  284. // d=(d-.999)*1000.;
  285. gl_FragColor = vec4( vec3( d ), 1.0 );
  286. }
  287. `
  288. };
  289. THREE.SSRrDepthShader = SSRrDepthShader;
  290. THREE.SSRrShader = SSRrShader;
  291. } )();