bevy_foliage_tool 0.16.2

A configurable foliage painting system using perlin noise, grayscale maps, and chunked visibility
Documentation
 
//see bindings in terrain_material.rs 
 
 //https://github.com/nicopap/bevy_mod_paramap/blob/main/src/parallax_map.wgsl

 // https://github.com/mikeam565/first-game/blob/main/assets/shaders/grass_shader.wgsl


#import bevy_pbr::mesh_functions::{mesh_position_local_to_clip, get_world_from_local , mesh_position_local_to_world}
 
 #import bevy_pbr::{
    
      mesh_view_bindings::view,
        mesh_view_bindings::globals,

        mesh_view_bindings as view_bindings,

         
      pbr_bindings,
      pbr_types,
        pbr_functions, 

    pbr_fragment::pbr_input_from_standard_material,
      pbr_functions::{ 
          prepare_world_normal,
          apply_normal_mapping,
          calculate_view 
      },
    // we can optionally modify the lit color before post-processing is applied
    pbr_types::{STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT,STANDARD_MATERIAL_FLAGS_UNLIT_BIT},
}




#ifdef PREPASS_PIPELINE
#import bevy_pbr::{
    prepass_io::{  FragmentOutput},
    pbr_deferred_functions::deferred_output,
}
#else
#import bevy_pbr::{
    forward_io::{VertexOutput,  FragmentOutput},
    pbr_functions::{apply_pbr_lighting, main_pass_post_lighting_processing, apply_fog,  alpha_discard},
}
#endif





// #import bevy_shader_utils::perlin_noise_2d::perlin_noise_2d


#import bevy_core_pipeline::tonemapping::tone_mapping
  
 #import bevy_pbr::pbr_types::StandardMaterial
 

 //https://dev.to/mikeam565/rust-game-dev-log-6-custom-vertex-shading-using-extendedmaterial-4312
//https://github.com/DGriffin91/bevy_mod_standard_material/blob/main/assets/shaders/pbr.wgsl




//@group(1) @binding(0)
//var base_color:  vec4<f32>;


// @group(1) @binding(0) var<uniform> base_material: StandardMaterial;
 

 
 

//should consider adding splat painting to this ..   performs a color shift 

  

 //mod the UV using parallax 
  // https://github.com/nicopap/bevy_mod_paramap/blob/main/src/parallax_map.wgsl

 //later ? 



// https://bevyengine.org/examples/shaders/shader-instancing/


// see https://github.com/bevyengine/bevy/blob/1030a99b8e2680a7e696d6433b79f5671768231c/crates/bevy_pbr/src/render/forward_io.wgsl#L32-L56

 

@group(2) @binding(20) var fog_cloud_noise: texture_2d<f32>;
@group(2) @binding(21) var fog_cloud_noise_sampler: sampler;


  





#ifdef PREPASS_PIPELINE




struct Vertex {
    @builtin(instance_index) instance_index: u32,
    @location(0) position: vec3<f32>,
    @location(1) blend_color: vec4<f32>,
  
};


@vertex
fn vertex(vertex: Vertex) -> bevy_pbr::prepass_io::VertexOutput {

    var out: bevy_pbr::prepass_io::VertexOutput;




    let time_base =  1.0  ;

    let sinewave_time = sin(  time_base  );

    var local_psn_output = vertex.position;

    local_psn_output.y = vertex.position.y * (1.0 + sin(  time_base +  vertex.position.x) *  0.20); 
    local_psn_output.x = vertex.position.x * (1.0 + cos(  time_base +  vertex.position.y) *  0.10 * vertex.position.y); 

    out.position = mesh_position_local_to_clip(
        get_world_from_local(vertex.instance_index),
        vec4<f32>(local_psn_output, 1.0),
    );


    return out;
}



#else





struct Vertex {
    @builtin(instance_index) instance_index: u32,
    @location(0) position: vec3<f32>,
    @location(1) blend_color: vec4<f32>,
    @location(2) uv: vec2<f32>,
};


/*
// could use the default  and toggle IFDEF ? 
struct VertexOutput {
    // This is `clip position` when the struct is used as a vertex stage output
    // and `frag coord` when used as a fragment stage input
    @builtin(position) position: vec4<f32>,
    @location(0) world_position: vec4<f32>,
    @location(1) world_normal: vec3<f32>, 
    @location(2) uv: vec2<f32>, 
    @location(5) color: vec4<f32>, 
}
*/


@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
    var out: VertexOutput;




    let time_base =  ( globals.time  ) * 1.0  ;

    let sinewave_time = sin(  time_base  );

    var local_psn_output = vertex.position;

    local_psn_output.y = vertex.position.y * (1.0 + sin(  time_base +  vertex.position.x) *  0.20); 
    local_psn_output.x = vertex.position.x * (1.0 + cos(  time_base +  vertex.position.y) *  0.10 * vertex.position.y); 

    //very important that we do this ! 
    out.world_position  =   mesh_position_local_to_world( 
        get_world_from_local(vertex.instance_index),   //  mat4x4<f32>
        vec4<f32>(local_psn_output, 1.0)   // vertex position 
        );


    out.position = mesh_position_local_to_clip(
        get_world_from_local(vertex.instance_index), //  mat4x4<f32>
        vec4<f32>(local_psn_output, 1.0),  // vertex position 
    );



  
        //define vertex color based on height  but not in prepass! 

  //  out.color =  mix( vec4<f32>(0.6,0.6,0.6,1.0),  vec4<f32>(1.0,1.0,1.0,1.0) , local_psn_output.y  ) ;
   
   
    //out.position = vertex.position;
    out.uv = vertex.uv ; 
   
    return out;
}


#endif






#ifdef PREPASS_PIPELINE
     @fragment
    fn  fragment(
     in: bevy_pbr::prepass_io::VertexOutput,
      
    ) -> @location(0) vec4<f32> {

       bevy_pbr::pbr_prepass_functions::prepass_alpha_discard(in);
    

         var out: vec4<f32>;

         return out ; 
     }

#else 


    @fragment
    fn fragment(
         
         in: VertexOutput,
             @builtin(front_facing) is_front: bool,
    ) -> @location(0) vec4<f32> {

        
     

        let uv_transform = pbr_bindings::material.uv_transform; 
        var uv = (uv_transform * vec3(in.uv, 1.0)).xy;
     
            
            // for now ? 
       let vertex_color = mix( vec4<f32>(1.0,1.0,1.0,1.0),  vec4<f32>(0.5,0.5,0.5,1.0) ,  uv.y  ) ;

         
        
        //how can i do a gradient in the vertical based on local_position !? 



          var bias  = view.mip_bias;
     
            // this is how you access std material stuff in an ext when using a vertex pass ! 
         var blended_color = pbr_bindings::material.base_color;   // this is nice and green ! 

          
          let tex_color  = textureSample(
                pbr_bindings::base_color_texture,
                pbr_bindings::base_color_sampler,
                uv,
                 
            );
      

        blended_color  *= tex_color ; 
         blended_color  *= vertex_color; 







         //manual alpha mask 
          if  ( blended_color.a < 0.2 ) {
          discard;
         }




         //use this along with a time offset to sample the fog noise map (uv)  to simulate darkening due to clouds above  !

         let world_position = in.world_position; 

          let fog_cloud_time_base = ( globals.time   * 0.01 )   % 1.0 ;

          let fog_cloud_world_pos_offset = vec2<f32>( abs(world_position.x ) , abs(world_position.z )  ) * 0.01 ;
          let fog_cloud_scroll =  vec2<f32>( fog_cloud_time_base  ,  fog_cloud_time_base  )  ;

            //aso need sine wave time shit on this uv input 
        var  fog_cloud_noise_uv = fog_cloud_world_pos_offset + fog_cloud_scroll ; 
        
         fog_cloud_noise_uv.x = fog_cloud_noise_uv.x % 1.0;  
         fog_cloud_noise_uv.y = fog_cloud_noise_uv.y % 1.0;  

        let fog_cloud_sample = textureSample(fog_cloud_noise, fog_cloud_noise_sampler, fog_cloud_noise_uv)  ;


      //  let fog_cloud_output = fog_cloud_sample.r;
         let highlight_color = vec4<f32>(1.0, 1.0, 1.0, 1.0);
         let shadow_color = vec4<f32>(0.25,0.25,0.25, 1.0);
      
         

        let fog_cloud_color = mix(shadow_color, highlight_color, fog_cloud_sample.r  );

        blended_color = blended_color * fog_cloud_color; 
        



        


      //  var pbr_input = pbr_input_from_standard_material(in, is_front);
          // pbr_input.material.base_color = blended_color ; // vec4<f32>(1.0, 1.0, 1.0, 1.0);



            //var pbr_out: FragmentOutput; 
           // pbr_out.color =  apply_pbr_lighting(pbr_input);  // ??? make this more efficient ? 
          //  let lighting_average  = (pbr_out.color.r + pbr_out.color.g + pbr_out.color.b ) / 3.0 ;


            // could do cel shader quantization here ? 

 

        //     pbr_out.color =  pbr_out.color* blended_color ;
          //  pbr_input.material.base_color = blended_color;


        //apply atmospheric fog ! 
        //the fog doesnt have proper falloff !? 
    //    pbr_out.color = main_pass_post_lighting_processing(pbr_input, pbr_out.color);


         let white_color = vec4<f32>(1.0, 1.0, 1.0, 1.0);  //use for fog ? 



      #ifdef DISTANCE_FOG
         let fog_output = apply_fog(view_bindings::fog,  blended_color , world_position.xyz, view_bindings::view.world_position.xyz);


        let final_color =   fog_output ;    

        #else 

         let final_color =   blended_color ;    



       #endif    
       
      
        
             return   final_color;
        
       
    }

 

 #endif