Picture

Technical shading @ Animal Logic. Special interest in lens simulation. To quote Matt Pharr: 'It seemed worth writing up at the time.'

On procedural welding in OSL

The burn variation could use some work …

ALGORIDDIM

Procedural welding is an interesting challenge since it’s not something you want to hand paint on every metal intersection. UV based techniques fail because we often cut out UV’s in the places were the welding occurs.

So, a little algorithm to calculate this procedurally needs to be devised:

  • Generate curves from edge loop and resample with point count equal to welding frequency
  • For every shading point:
    • Calculate the distance to every curve point
    • Compare distance to user-set welding radius to determine displacement amount (could use a ramp to look up a certain value)
    • If distance to point N is smallest and if distance to point N+1 is also within the radius
      • Add displacements of both lookups of N and N+1

Imagine the two scenarios. A point within the welding radius, and a point outside the welding radius. What are the conditions for both?

If we disregard the welding overlapping, I am only interested in the closest point. In the simplest case, you can reason that if the distance between the shading point and the closest curve point is smaller than the welding radius, we should displace. If the distance is larger than the radius, no work needs to be done.

That’s all there is to it really.

This ramp defines the profile of the weld

This was a challenge held on www.shaders.xyz, so there’s lots more cool approaches to explore over there:

CODE

The base algorithm works, but the way the pointdata input/output is done is really bad. It’d be better to add it as a primvar and read it straight from the geometry. Someone else can do the cleanup, this worked for what I needed it to ¯\_(ツ)_/¯

The output of the shader packed in 3 channels: the welding displacement in R, a weld probability in G and the burn radius in B.

  float rand(float n){
      return sin(n) * 43758.5453123 - floor(sin(n) * 43758.5453123);
  }

  shader weld(
      float radius = 0.1,
      float disp_height = 1.0,
      vector distort = vector(0),
      float burn_radius = 1.0,
      string profile_tex = "C:/ZENO_2019/projects/shaders_xyz/challenge_08_weld/src/weld_05.tiff",
      
      output vector disp_rand_burn = vector(0)
  ) {
      float x[126] = {-2.9594118652905284, -3.06659561162177, -3.111245635732151, -3.1173295968071453, -3.1050986451205116, -3.0859546982716526, -3.063474038757438, -3.0385908555401135, -3.015196974384542, -2.993531809868379, -2.9727787328604296, -2.9530577806178235, -2.93567014712943, -2.9214029610795857, -2.9106195235692796, -2.9035153644679452, -2.900758127419323, -2.9027009915787576, -2.9089601831861867, -2.9188107697622225, -2.9318145121955133, -2.9473946179507315, -2.965156209462176, -2.984353551890091, -3.0050064797872977, -3.028167584295044, -3.0546114528062343, -3.079672314989936, -3.101178333784778, -3.115825526294749, -3.1118469283879593, -3.066615441452037, -2.959063326683403, -2.8394350212516506, -2.715187900834451, -2.5913130963242508, -2.4685810041569898, -2.3507086894135374, -2.2375538782221347, -2.1282960859750606, -2.025346408406013, -1.9320559747894825, -1.8505739945542088, -1.7830103047735817, -1.7315726048487357, -1.6986613569299118, -1.6870988644668388, -1.6983242167481944, -1.731005801413018, -1.7823652849311664, -1.8500999387880206, -1.931954542836634, -2.0255185894827674, -2.128534078877159, -2.237756869865205, -2.350823771435911, -2.4684334754178563, -2.5911537478147486, -2.7151141807095787, -2.8395819720573194, -2.8395819720573194, -2.8395819720573194, -2.8395819720573194, -0.8671446799542128, -0.8106879030105469, -0.7627101046787095, -0.7188909002027845, -0.6790434462021224, -0.6446508998598287, -0.6180295725762448, -0.5989970793857821, -0.5877064015030522, -0.5847084755800768, -0.5903576219474312, -0.6041133111718161, -0.6253756224644738, -0.6541968465084352, -0.6899327988694073, -0.7308233672140579, -0.7747811400967087, -0.8254819692903786, -0.8824186011750184, -0.9314811778342709, -0.9696025920977192, -0.9770691255272971, -0.9197284158778207, -0.8120137316914043, -0.6962553773820508, -0.5732157364877815, -0.4488788593730335, -0.32349396438989464, -0.19877890382687805, -0.07563567279013914, 0.044634694715454074, 0.16249994929344486, 0.2772951059710919, 0.387558664050153, 0.4909816985135227, 0.5849247283402627, 0.6659206573332158, 0.729606094194807, 0.7705022484126575, 0.7826358573473955, 0.7631208411113708, 0.7162275085299262, 0.6478660252966125, 0.563317787305782, 0.46668985565112475, 0.3613554327453721, 0.24976598467077785, 0.1341384206311771, 0.015642757410028213, -0.10530049322046446, -0.22911551747104114, -0.3541233072752549, -0.47956548845317654, -0.603780921535201, -0.7256085866491223, -0.8399765296331321, -0.9402637775492637, -0.9779007953970165, -0.9596833115008329, -0.9181076422598139, -0.9181076422598139, -0.9181076422598139, -0.9181076422598139};
      float y[126] = {-0.09716461424764485, -0.10293167928383322, -0.09716452436805992, -0.0856351339667881, -0.06946985096774198, -0.04904160445873779, -0.018874891833365926, 0.026691598405791203, 0.08271590975770608, 0.14608690528954704, 0.21947719875312396, 0.3051198070555168, 0.402136514386926, 0.5094200656765558, 0.6253526978628826, 0.7479529231060187, 0.8744506820718716, 1.0009561110610528, 1.1235655262691138, 1.2394794372857263, 1.3466413318186676, 1.4433484050598462, 1.5287835828365577, 1.6022761277153326, 1.6659491996082803, 1.7224915538110945, 1.7696827454683721, 1.801137039507999, 1.8222006732115836, 1.8387136178972041, 1.8505444472122936, 1.85627303066601, 1.8503455722341462, 1.8387378227589581, 1.8225201373553692, 1.8019754104541827, 1.7714505118443467, 1.7252602888220843, 1.6689724621357762, 1.6054601675352107, 1.5319757648001964, 1.4462944637632917, 1.3493026761543505, 1.2420411482313065, 1.126134086381827, 1.0035537717339533, 0.8770678677492209, 0.7505494857721787, 0.627896998502999, 0.5119491670495003, 0.4047947428852657, 0.3081718770589287, 0.22290082920235235, 0.1496435023119004, 0.08617823199533052, 0.029750156006267854, -0.017167389252699738, -0.04827232713729237, -0.06909935406667501, -0.08547358070289442, -0.08547358070289442, -0.08547358070289442, -0.08547358070289442, -0.020437595440241152, 0.03770562611170646, 0.10746981015540323, 0.1868477123172677, 0.2808474854356216, 0.3871894789681683, 0.504123974204333, 0.629077476349126, 0.7599498786023869, 0.893950940976469, 1.0275230244815359, 1.1572400469105566, 1.280486652290282, 1.3950096273819728, 1.4983641308774742, 1.5885070133821506, 1.6649092586391578, 1.732541967759523, 1.7847639134143791, 1.8151640098372341, 1.8366048494797134, 1.8513693634133468, 1.8559766961707826, 1.85075275572286, 1.8419905139263029, 1.8299206699349737, 1.8152223332840849, 1.7961194125266982, 1.77007561476508, 1.7333331411750468, 1.688272937200366, 1.6376190533308046, 1.5797755256454398, 1.5126305759655654, 1.4339770323027585, 1.3429581042579295, 1.238915825532882, 1.1222083415265653, 0.9945455467418065, 0.8602983533953694, 0.7270306342673277, 0.6017144629819967, 0.48798970965276706, 0.38716610901970067, 0.2993860735995098, 0.22370745024418096, 0.1591735438807055, 0.10317588539637769, 0.05398320095090165, 0.010265133357050133, -0.023912351359255717, -0.0480360212557945, -0.06589941883069239, -0.07994276514147074, -0.091261255960812, -0.09927876204215184, -0.10269165499955653, -0.09481222734775391, -0.07830130547759001, -0.05492151964485851, -0.05492151964485851, -0.05492151964485851, -0.0549215196448585};
      float z[126] = {-0.013164922069520552, 0.06254023910195622, 0.1858272159554273, 0.3113553702090737, 0.43684098354365375, 0.560007516723617, 0.6811284198923229, 0.7967188648673758, 0.9077712211955519, 1.015216847542288, 1.1163774380857283, 1.2077714194591775, 1.2874971863825857, 1.3536320168541365, 1.4039834598605498, 1.4361117562901853, 1.4472627881162377, 1.4360321962697682, 1.4037411113205411, 1.3531546954138434, 1.2865373148956123, 1.2060664661955758, 1.1140942053185403, 1.012717330104907, 0.9052463932254309, 0.7944248315609028, 0.6798496499001452, 0.5595478419129031, 0.4368577677120907, 0.3117062668343374, 0.18600959352657007, 0.06269831892744178, -0.01218723083448602, -0.05068432733056008, -0.071939878539517, -0.08575676773763904, -0.09537838954331006, -0.1009199583346225, -0.10752827587534108, -0.11524683220750419, -0.12236590422444149, -0.12799198289573802, -0.1328198411889716, -0.13700651016665413, -0.14035636582731806, -0.1424480512906083, -0.14324245698436386, -0.14271411345758003, -0.1407894421827037, -0.1374192147379727, -0.13277368371519607, -0.12683423762493526, -0.1198393595680353, -0.11157583983845774, -0.10305502565070686, -0.09619058317211354, -0.09157136026034209, -0.08353654218310248, -0.07107300356155623, -0.051109247829072724, -0.051109247829072724, -0.051109247829072724, -0.051109247829072724, -2.218199555108801, -2.1111830497445907, -2.007421658541009, -1.9087776979165318, -1.8215714731344128, -1.7474867363096067, -1.6872424551988077, -1.6423215936093605, -1.6146818494048794, -1.6064460584214373, -1.6191127428996583, -1.6506424603603829, -1.6992134773690937, -1.762915602099953, -1.8406025463128295, -1.9312455845525194, -2.0320968267801005, -2.1361178757427006, -2.2458119778487378, -2.3674876748243876, -2.493521033623645, -2.6295064313281955, -2.755754801286207, -2.8397876351252065, -2.9047438556068226, -2.957805659178662, -3.0042106595364464, -3.047454327899631, -3.0884782717326287, -3.1263205775546523, -3.164000819574609, -3.202205679866729, -3.239704019851754, -3.275435343540394, -3.3083690495086526, -3.337904894364018, -3.363045134090327, -3.382503432667225, -3.3946399597555805, -3.3981305985548347, -3.392527914638525, -3.378517641793861, -3.3575420648297265, -3.331177546275642, -3.3005979314865947, -3.266846257414209, -3.230490455406774, -3.1927963438798037, -3.154659205367898, -3.1174879665097563, -3.0794256325084994, -3.0381294739174174, -2.994656924381171, -2.9474791736158874, -2.8916937671810428, -2.823932175661435, -2.7295639026938785, -2.5958890968823445, -2.4628668719417233, -2.3378779386455903, -2.3378779386455903, -2.3378779386455903, -2.3378779386455903};
      float distances[126];
      int min_dist_cv = 0;
      vector shading_pos = P;
      float min_dist = 9999999999.0;

      for (int i = 0; i < 125; i++){
          point pos = point(x[i], y[i], z[i]);
          pos += distort;

          // find distance between two points
          float distance = sqrt((P[0] - pos[0])*(P[0] - pos[0]) + 
                                (P[1] - pos[1])*(P[1] - pos[1]) +
                                (P[2] - pos[2])*(P[2] - pos[2]) );
          
          distances[i] = distance;

          if (distance < min_dist){
              min_dist = distance;
              min_dist_cv = i;
          }
      }

      if (distances[min_dist_cv] < burn_radius){
          disp_rand_burn[2] = 1.0 - (distances[min_dist_cv] / burn_radius);
      }

      if ((min_dist < radius)){
          float min_dist_norm = min_dist/radius;
          float disp_lookup = texture(profile_tex, min_dist_norm, 0.0);
          disp_rand_burn[0] += disp_lookup;
          disp_rand_burn[1] = rand(min_dist_cv/float(125));

          if (min_dist_cv < 125 && (distances[min_dist_cv+1] < radius)){
              float min_dist_1_norm = distances[min_dist_cv+1]/radius;
              float disp_lookup = texture(profile_tex, min_dist_1_norm, 0.0);
              disp_rand_burn[0] += disp_lookup;
          }

          if (min_dist_cv > 0 && (distances[min_dist_cv-1] < radius)){
              float min_dist_2_norm = distances[min_dist_cv-1]/radius;
              float disp_lookup = texture(profile_tex, min_dist_2_norm, 0.0);
              disp_rand_burn[0] += disp_lookup;
          }
      }

      disp_rand_burn[0] = (disp_rand_burn[0]/2.0) * disp_height;

  }