SSRrShader.js 7.9 KB

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