<commit_before>//! Read and draw terrain data in 3D.

use gl;
use yaglw::gl_context::GLContext;
use yaglw::shader::Shader;

#[allow(missing_docs)]
pub struct TerrainShader<'a> {
  #[allow(missing_docs)]
  pub shader: Shader<'a>,
}

impl<'a> TerrainShader<'a> {
  #[allow(missing_docs)]
  pub fn new<'b:'a>(gl: &'a GLContext) -> TerrainShader<'b> {
    let components = vec!(
      (gl::VERTEX_SHADER, "
        #version 330 core

        uniform mat4 projection_matrix;

        uniform samplerBuffer positions;
        uniform samplerBuffer normals;

        flat out int face_id;
        out vec3 world_position;
        out vec3 normal;

        void main() {
          // Mutiply by 3 because there are 3 components for each normal vector.
          int position_id = gl_VertexID * 3;
          world_position.x = texelFetch(positions, position_id + 0).r;
          world_position.y = texelFetch(positions, position_id + 1).r;
          world_position.z = texelFetch(positions, position_id + 2).r;

          int normal_id = position_id;
          normal.x = texelFetch(normals, normal_id + 0).r;
          normal.y = texelFetch(normals, normal_id + 1).r;
          normal.z = texelFetch(normals, normal_id + 2).r;

          face_id = gl_VertexID / 3;

          gl_Position = projection_matrix * vec4(world_position, 1.0);
        }".to_string()),
      (gl::FRAGMENT_SHADER, format!("
        #version 330 core

        uniform struct Sun {{
          vec3 direction;
          vec3 intensity;
        }} sun;

        uniform vec3 ambient_light;

        uniform samplerBuffer positions;

        flat in int face_id;
        in vec3 world_position;
        in vec3 normal;

        out vec4 frag_color;

        float perlin(const float x, const float y) {{
          float amplitude = 1;
          float frequency = 1.0 / 64.0;
          float persistence = 0.8;
          const float lacunarity = 2.4;
          const int octaves = 2;

          float r = 0.0;
          float max_crest = 0.0;

          for (int o = 0; o < octaves; ++o) {{
            float f = frequency * 2 * 3.14;
            r += amplitude * (sin((o+x) * f) + sin((o+y) * f)) / 2;

            max_crest += amplitude;
            amplitude *= persistence;
            frequency *= lacunarity;
          }}

          // Scale to [-1, 1]. N.B. There is no clamping.
          r /= max_crest;

          return r;
        }}

        void main() {{
          int color_id = face_id * 3;

          vec4 base_color;

          float p = perlin(world_position.x, world_position.z);
          // shift, scale, clamp to [0, 1]
          p = (p + 1) / 2;
          p = clamp(p, 0, 1);

          base_color.r = (1 - p) / 2;<commit_msg>terrain coloring is not height-independent<commit_after>//! Read and draw terrain data in 3D.

use gl;
use yaglw::gl_context::GLContext;
use yaglw::shader::Shader;

#[allow(missing_docs)]
pub struct TerrainShader<'a> {
  #[allow(missing_docs)]
  pub shader: Shader<'a>,
}

impl<'a> TerrainShader<'a> {
  #[allow(missing_docs)]
  pub fn new<'b:'a>(gl: &'a GLContext) -> TerrainShader<'b> {
    let components = vec!(
      (gl::VERTEX_SHADER, "
        #version 330 core

        uniform mat4 projection_matrix;

        uniform samplerBuffer positions;
        uniform samplerBuffer normals;

        flat out int face_id;
        out vec3 world_position;
        out vec3 normal;

        void main() {
          // Mutiply by 3 because there are 3 components for each normal vector.
          int position_id = gl_VertexID * 3;
          world_position.x = texelFetch(positions, position_id + 0).r;
          world_position.y = texelFetch(positions, position_id + 1).r;
          world_position.z = texelFetch(positions, position_id + 2).r;

          int normal_id = position_id;
          normal.x = texelFetch(normals, normal_id + 0).r;
          normal.y = texelFetch(normals, normal_id + 1).r;
          normal.z = texelFetch(normals, normal_id + 2).r;

          face_id = gl_VertexID / 3;

          gl_Position = projection_matrix * vec4(world_position, 1.0);
        }".to_string()),
      (gl::FRAGMENT_SHADER, format!("
        #version 330 core

        uniform struct Sun {{
          vec3 direction;
          vec3 intensity;
        }} sun;

        uniform vec3 ambient_light;

        uniform samplerBuffer positions;

        flat in int face_id;
        in vec3 world_position;
        in vec3 normal;

        out vec4 frag_color;

        float perlin(const float x, const float y) {{
          float amplitude = 1;
          float frequency = 1.0 / 64.0;
          float persistence = 0.8;
          const float lacunarity = 2.4;
          const int octaves = 2;

          float r = 0.0;
          float max_crest = 0.0;

          for (int o = 0; o < octaves; ++o) {{
            float f = frequency * 2 * 3.14;
            r += amplitude * (sin((o+x) * f) + sin((o+y) * f)) / 2;

            max_crest += amplitude;
            amplitude *= persistence;
            frequency *= lacunarity;
          }}

          // Scale to [-1, 1]. N.B. There is no clamping.
          r /= max_crest;

          return r;
        }}

        void main() {{
          int color_id = face_id * 3;

          vec4 base_color = vec4(0, 0.5, 0, 1);

          float p = 0
            + perlin(0, world_position.x)
            + perlin(0, world_position.y)
            + perlin(0, world_position.z)
          ;

          // shift, scale, clamp to [0, 1]
          p = (p + 3) / 6;
          p = clamp(p, 0, 1);

          base_color.r = (1 - p) / 2;
{'fraction_non_alphanumeric': 0.1134446239454317, 'fraction_numerical': 0.024053132292227608, 'mean_word_length': 1.8184117349519473, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5772587', 'n_tokens_mistral': 1882, 'n_tokens_neox': 1748, 'n_words': 494}