Advertisement
Guest User

Untitled

a guest
Oct 2nd, 2019
165
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. [compute]
  2.  
  3. #version 450
  4.  
  5. VERSION_DEFINES
  6.  
  7. layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
  8.  
  9. #define NO_CHILDREN 0xFFFFFFFF
  10. #define GREY_VEC vec3(0.33333,0.33333,0.33333)
  11.  
  12. struct CellChildren {
  13.     uint children[8];
  14. };
  15.  
  16. layout(set=0,binding=1,std430) buffer CellChildrenBuffer {
  17.     CellChildren data[];
  18. } cell_children;
  19.  
  20. struct CellData {
  21.     uint position; // xyz 10 bits
  22.     uint albedo; //rgb albedo
  23.     uint emission; //rgb normalized with e as multiplier
  24.     uint normal; //RGB normal encoded
  25. };
  26.  
  27. layout(set=0,binding=2,std430) buffer CellDataBuffer {
  28.     CellData data[];
  29. } cell_data;
  30.  
  31. #define LIGHT_TYPE_DIRECTIONAL 0
  32. #define LIGHT_TYPE_OMNI 1
  33. #define LIGHT_TYPE_SPOT 2
  34.  
  35. #ifdef MODE_COMPUTE_LIGHT
  36.  
  37. struct Light {
  38.  
  39.     uint type;
  40.     float energy;
  41.     float radius;
  42.     float attenuation;
  43.  
  44.     vec3 color;
  45.     float spot_angle_radians;
  46.  
  47.     vec3 position;
  48.     float spot_attenuation;
  49.  
  50.     vec3 direction;
  51.     bool has_shadow;
  52. };
  53.  
  54.  
  55. layout(set=0,binding=3,std140) uniform Lights {
  56.     Light data[MAX_LIGHTS];
  57. } lights;
  58.  
  59. #endif
  60.  
  61. layout(push_constant, binding = 0, std430) uniform Params {
  62.  
  63.     ivec3 limits;
  64.     uint stack_size;
  65.  
  66.     float emission_scale;
  67.     float propagation;
  68.     float dynamic_range;
  69.  
  70.     uint light_count;
  71.     uint cell_offset;
  72.     uint cell_count;
  73.     uint pad[2];
  74.  
  75. } params;
  76.  
  77.  
  78. layout(set=0,binding=4,std430) buffer Outputs {
  79.     vec4 data[];
  80. } outputs;
  81.  
  82. #ifdef MODE_WRITE_TEXTURE
  83.  
  84. layout (rgba8,set=0,binding=5) uniform restrict writeonly image3D color_tex;
  85.  
  86. #ifdef MODE_ANISOTROPIC
  87.  
  88. layout (r16ui,set=0,binding=6) uniform restrict writeonly uimage3D aniso_pos_tex;
  89. layout (r16ui,set=0,binding=7) uniform restrict writeonly uimage3D aniso_neg_tex;
  90.  
  91. #endif
  92.  
  93.  
  94. #endif
  95.  
  96.  
  97. #ifdef MODE_COMPUTE_LIGHT
  98.  
  99. uint raymarch(float distance,float distance_adv,vec3 from,vec3 direction) {
  100.  
  101.     uint result = NO_CHILDREN;
  102.  
  103.     ivec3 size = ivec3(max(max(params.limits.x,params.limits.y),params.limits.z));
  104.  
  105.     while (distance > -distance_adv) { //use this to avoid precision errors
  106.  
  107.         uint cell = 0;
  108.  
  109.         ivec3 pos = ivec3(from);
  110.  
  111.         if (all(greaterThanEqual(pos,ivec3(0))) && all(lessThan(pos,size))) {
  112.  
  113.             ivec3 ofs = ivec3(0);
  114.             ivec3 half_size = size / 2;
  115.  
  116.             for (int i = 0; i < params.stack_size - 1; i++) {
  117.  
  118.                 bvec3 greater = greaterThanEqual(pos,ofs+half_size);
  119.  
  120.                 ofs += mix(ivec3(0),half_size,greater);
  121.  
  122.                 uint child = 0; //wonder if this can be done faster
  123.                 if (greater.x) {
  124.                     child|=1;
  125.                 }
  126.                 if (greater.y) {
  127.                     child|=2;
  128.                 }
  129.                 if (greater.z) {
  130.                     child|=4;
  131.                 }
  132.  
  133.                 cell = cell_children.data[cell].children[child];
  134.                 if (cell == NO_CHILDREN)
  135.                     break;
  136.  
  137.                 half_size >>= ivec3(1);
  138.             }
  139.  
  140.             if ( cell != NO_CHILDREN) {
  141.                 return cell; //found cell!
  142.             }
  143.  
  144.         }
  145.  
  146.         from += direction * distance_adv;
  147.         distance -= distance_adv;
  148.     }
  149.  
  150.     return NO_CHILDREN;
  151. }
  152.  
  153. bool compute_light_vector(uint light,uint cell, vec3 pos,out float attenuation, out vec3 light_pos) {
  154.  
  155.  
  156.     if (lights.data[light].type==LIGHT_TYPE_DIRECTIONAL) {
  157.  
  158.         light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
  159.         attenuation = 1.0;
  160.  
  161.     } else {
  162.  
  163.         light_pos = lights.data[light].position;
  164.         float distance = length(pos - light_pos);
  165.         if (distance >= lights.data[light].radius) {
  166.             return false;
  167.         }
  168.  
  169.  
  170.         attenuation = pow( clamp( 1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation );
  171.  
  172.  
  173.         if (lights.data[light].type==LIGHT_TYPE_SPOT) {
  174.  
  175.             vec3 rel = normalize(pos - light_pos);
  176.             float angle = acos(dot(rel,lights.data[light].direction));
  177.             if (angle > lights.data[light].spot_angle_radians) {
  178.                 return false;
  179.             }
  180.  
  181.             float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
  182.             attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
  183.         }
  184.     }
  185.  
  186.     return true;
  187. }
  188.  
  189. float get_normal_advance(vec3 p_normal) {
  190.  
  191.     vec3 normal = p_normal;
  192.     vec3 unorm = abs(normal);
  193.  
  194.     if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
  195.         // x code
  196.         unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
  197.     } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
  198.         // y code
  199.         unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
  200.     } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
  201.         // z code
  202.         unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
  203.     } else {
  204.         // oh-no we messed up code
  205.         // has to be
  206.         unorm = vec3(1.0, 0.0, 0.0);
  207.     }
  208.  
  209.     return 1.0 / dot(normal,unorm);
  210. }
  211.  
  212. #endif
  213.  
  214.  
  215.  
  216.  
  217. void main() {
  218.  
  219.     uint cell_index = gl_GlobalInvocationID.x;;
  220.     if (cell_index >= params.cell_count) {
  221.         return;
  222.     }
  223.     cell_index += params.cell_offset;
  224.  
  225.     uvec3 posu = uvec3(cell_data.data[cell_index].position&0x7FF,(cell_data.data[cell_index].position>>11)&0x3FF,cell_data.data[cell_index].position>>21);
  226.     vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo);
  227.  
  228. #ifdef MODE_COMPUTE_LIGHT
  229.  
  230.     vec3 pos = vec3(posu) + vec3(0.5);
  231.  
  232.     vec3 emission = vec3(ivec3(cell_data.data[cell_index].emission&0x3FF,(cell_data.data[cell_index].emission>>10)&0x7FF,cell_data.data[cell_index].emission>>21)) * params.emission_scale;
  233.     vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal);
  234.  
  235. #ifdef MODE_ANISOTROPIC
  236.     vec3 accum[6]=vec3[](vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));
  237.     const vec3 accum_dirs[6]=vec3[](vec3(1.0,0.0,0.0),vec3(-1.0,0.0,0.0),vec3(0.0,1.0,0.0),vec3(0.0,-1.0,0.0),vec3(0.0,0.0,1.0),vec3(0.0,0.0,-1.0));
  238. #else
  239.     vec3 accum = vec3(0.0);
  240. #endif
  241.  
  242.     for(uint i=0;i<params.light_count;i++) {
  243.  
  244.         float attenuation;
  245.         vec3 light_pos;
  246.  
  247.         if (!compute_light_vector(i,cell_index,pos,attenuation,light_pos)) {
  248.             continue;
  249.         }
  250.  
  251.         vec3 light_dir = pos - light_pos;
  252.         float distance = length(light_dir);
  253.         light_dir=normalize(light_dir);
  254.  
  255.         if (length(normal.xyz) > 0.2 && dot(normal.xyz,light_dir)>=0) {
  256.             continue; //not facing the light
  257.         }
  258.  
  259.         if (lights.data[i].has_shadow) {
  260.  
  261.             float distance_adv = get_normal_advance(light_dir);
  262.  
  263.  
  264.             distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always
  265.  
  266.             vec3 from = pos - light_dir * distance; //approximate
  267.             from -= sign(light_dir)*0.45; //go near the edge towards the light direction to avoid self occlusion
  268.  
  269.  
  270.  
  271.             uint result = raymarch(distance,distance_adv,from,light_dir);
  272.  
  273.             if (result != cell_index) {
  274.                 continue; //was occluded
  275.             }
  276.         }
  277.  
  278.         vec3 light = lights.data[i].color * albedo.rgb * attenuation * lights.data[i].energy;
  279.  
  280. #ifdef MODE_ANISOTROPIC
  281.         for(uint j=0;j<6;j++) {
  282.  
  283.             accum[j]+=max(0.0,dot(accum_dirs[j],-light_dir))*light+emission;
  284.         }
  285. #else
  286.         if (length(normal.xyz) > 0.2) {
  287.             accum+=max(0.0,dot(normal.xyz,-light_dir))*light+emission;
  288.         } else {
  289.             //all directions
  290.             accum+=light+emission;
  291.         }
  292. #endif
  293.  
  294.     }
  295.  
  296. #ifdef MODE_ANISOTROPIC
  297.  
  298.     outputs.data[cell_index*6+0]=vec4(accum[0],0.0);
  299.     outputs.data[cell_index*6+1]=vec4(accum[1],0.0);
  300.     outputs.data[cell_index*6+2]=vec4(accum[2],0.0);
  301.     outputs.data[cell_index*6+3]=vec4(accum[3],0.0);
  302.     outputs.data[cell_index*6+4]=vec4(accum[4],0.0);
  303.     outputs.data[cell_index*6+5]=vec4(accum[5],0.0);
  304. #else
  305.     outputs.data[cell_index]=vec4(accum,0.0);
  306.  
  307. #endif
  308.  
  309. #endif //MODE_COMPUTE_LIGHT
  310.  
  311.  
  312. #ifdef MODE_UPDATE_MIPMAPS
  313.  
  314.     {
  315. #ifdef MODE_ANISOTROPIC
  316.         vec3 light_accum[6] = vec3[](vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));
  317. #else
  318.         vec3 light_accum = vec3(0.0);
  319. #endif
  320.         float count = 0.0;
  321.         for(uint i=0;i<8;i++) {
  322.             uint child_index = cell_children.data[cell_index].children[i];
  323.             if (child_index==NO_CHILDREN) {
  324.                 continue;
  325.             }
  326. #ifdef MODE_ANISOTROPIC
  327.             light_accum[0] += outputs.data[child_index*6+0].rgb;
  328.             light_accum[1] += outputs.data[child_index*6+1].rgb;
  329.             light_accum[2] += outputs.data[child_index*6+2].rgb;
  330.             light_accum[3] += outputs.data[child_index*6+3].rgb;
  331.             light_accum[4] += outputs.data[child_index*6+4].rgb;
  332.             light_accum[5] += outputs.data[child_index*6+5].rgb;
  333.  
  334. #else
  335.             light_accum += outputs.data[child_index].rgb;
  336.  
  337. #endif
  338.  
  339.             count+=1.0;
  340.         }
  341.  
  342.         float divisor = mix(8.0,count,params.propagation);
  343. #ifdef MODE_ANISOTROPIC
  344.         outputs.data[cell_index*6+0]=vec4(light_accum[0] / divisor,0.0);
  345.         outputs.data[cell_index*6+1]=vec4(light_accum[1] / divisor,0.0);
  346.         outputs.data[cell_index*6+2]=vec4(light_accum[2] / divisor,0.0);
  347.         outputs.data[cell_index*6+3]=vec4(light_accum[3] / divisor,0.0);
  348.         outputs.data[cell_index*6+4]=vec4(light_accum[4] / divisor,0.0);
  349.         outputs.data[cell_index*6+5]=vec4(light_accum[5] / divisor,0.0);
  350.  
  351. #else
  352.         outputs.data[cell_index]=vec4(light_accum / divisor,0.0);
  353. #endif
  354.  
  355.  
  356.  
  357.     }
  358. #endif
  359.  
  360. #ifdef MODE_WRITE_TEXTURE
  361.     {
  362.  
  363. #ifdef MODE_ANISOTROPIC
  364.         vec3 accum_total = vec3(0.0);
  365.         accum_total += outputs.data[cell_index*6+0].rgb;
  366.         accum_total += outputs.data[cell_index*6+1].rgb;
  367.         accum_total += outputs.data[cell_index*6+2].rgb;
  368.         accum_total += outputs.data[cell_index*6+3].rgb;
  369.         accum_total += outputs.data[cell_index*6+4].rgb;
  370.         accum_total += outputs.data[cell_index*6+5].rgb;
  371.  
  372.         float accum_total_energy = max(dot(accum_total,GREY_VEC),0.00001);
  373.         vec3 iso_positive = vec3(dot(outputs.data[cell_index*6+0].rgb,GREY_VEC),dot(outputs.data[cell_index*6+2].rgb,GREY_VEC),dot(outputs.data[cell_index*6+4].rgb,GREY_VEC))/vec3(accum_total_energy);
  374.         vec3 iso_negative = vec3(dot(outputs.data[cell_index*6+1].rgb,GREY_VEC),dot(outputs.data[cell_index*6+3].rgb,GREY_VEC),dot(outputs.data[cell_index*6+5].rgb,GREY_VEC))/vec3(accum_total_energy);
  375.  
  376.  
  377.         {
  378.             uint aniso_pos = uint(clamp(iso_positive.b * 31.0,0.0,31.0));
  379.             aniso_pos |= uint(clamp(iso_positive.g * 63.0,0.0,63.0))<<5;
  380.             aniso_pos |= uint(clamp(iso_positive.r * 31.0,0.0,31.0))<<11;
  381.             imageStore(aniso_pos_tex,ivec3(posu),uvec4(aniso_pos));
  382.         }
  383.  
  384.         {
  385.             uint aniso_neg = uint(clamp(iso_negative.b * 31.0,0.0,31.0));
  386.             aniso_neg |= uint(clamp(iso_negative.g * 63.0,0.0,63.0))<<5;
  387.             aniso_neg |= uint(clamp(iso_negative.r * 31.0,0.0,31.0))<<11;
  388.             imageStore(aniso_neg_tex,ivec3(posu),uvec4(aniso_neg));
  389.         }
  390.  
  391.         imageStore(color_tex,ivec3(posu),vec4(accum_total / params.dynamic_range ,albedo.a));
  392.  
  393. #else
  394.  
  395.         imageStore(color_tex,ivec3(posu),vec4(outputs.data[cell_index].rgb / params.dynamic_range,albedo.a));
  396.  
  397. #endif
  398.  
  399.  
  400.     }
  401. #endif
  402. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement