From 72a6e364292842c792242755ef01778ad5189ade Mon Sep 17 00:00:00 2001
From: Quaternions <krakow20@gmail.com>
Date: Wed, 30 Aug 2023 15:18:05 -0700
Subject: [PATCH] add ground pipeline

---
 src/main.rs     | 32 ++++++++++++++++++++++++++++++++
 src/shader.wgsl | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/src/main.rs b/src/main.rs
index 99025753e..b843eae95 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -56,6 +56,7 @@ pub struct Skybox {
     camera: Camera,
     sky_pipeline: wgpu::RenderPipeline,
     entity_pipeline: wgpu::RenderPipeline,
+    ground_pipeline: wgpu::RenderPipeline,
     bind_group: wgpu::BindGroup,
     uniform_buf: wgpu::Buffer,
     entities: Vec<Entity>,
@@ -251,6 +252,33 @@ impl strafe_client::framework::Example for Skybox {
             multisample: wgpu::MultisampleState::default(),
             multiview: None,
         });
+        let ground_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
+            label: Some("Ground"),
+            layout: Some(&pipeline_layout),
+            vertex: wgpu::VertexState {
+                module: &shader,
+                entry_point: "vs_ground",
+                buffers: &[],
+            },
+            fragment: Some(wgpu::FragmentState {
+                module: &shader,
+                entry_point: "fs_ground",
+                targets: &[Some(config.view_formats[0].into())],
+            }),
+            primitive: wgpu::PrimitiveState {
+                front_face: wgpu::FrontFace::Cw,
+                ..Default::default()
+            },
+            depth_stencil: Some(wgpu::DepthStencilState {
+                format: Self::DEPTH_FORMAT,
+                depth_write_enabled: false,
+                depth_compare: wgpu::CompareFunction::LessEqual,
+                stencil: wgpu::StencilState::default(),
+                bias: wgpu::DepthBiasState::default(),
+            }),
+            multisample: wgpu::MultisampleState::default(),
+            multiview: None,
+        });
 
         let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
             label: None,
@@ -360,6 +388,7 @@ impl strafe_client::framework::Example for Skybox {
             camera,
             sky_pipeline,
             entity_pipeline,
+            ground_pipeline,
             bind_group,
             uniform_buf,
             entities,
@@ -449,6 +478,9 @@ impl strafe_client::framework::Example for Skybox {
                 rpass.draw(0..entity.vertex_count, 0..1);
             }
 
+            rpass.set_pipeline(&self.ground_pipeline);
+            rpass.draw(0..3, 0..1);
+
             rpass.set_pipeline(&self.sky_pipeline);
             rpass.draw(0..3, 0..1);
         }
diff --git a/src/shader.wgsl b/src/shader.wgsl
index deb67153c..7ae2d05cc 100644
--- a/src/shader.wgsl
+++ b/src/shader.wgsl
@@ -39,6 +39,32 @@ fn vs_sky(@builtin(vertex_index) vertex_index: u32) -> SkyOutput {
     return result;
 }
 
+struct GroundOutput {
+    @builtin(position) position: vec4<f32>,
+    @location(1) normal: vec3<f32>,
+    @location(3) view: vec3<f32>,
+    @location(4) pos: vec3<f32>,
+};
+
+@vertex
+fn vs_ground(@builtin(vertex_index) vertex_index: u32) -> GroundOutput {
+    // hacky way to draw two triangles that make a square
+    let tmp1 = (i32(vertex_index)-i32(vertex_index)/3*2) / 2;
+    let tmp2 = (i32(vertex_index)-i32(vertex_index)/3*2) & 1;
+    let pos = vec3<f32>(
+        f32(tmp1) * 2.0 - 1.0,
+        0.0,
+        f32(tmp2) * 2.0 - 1.0
+    ) * 100.0;
+
+    var result: GroundOutput;
+    result.normal = vec3<f32>(0.0,1.0,0.0);
+    result.pos = pos;
+    result.view = pos - r_data.cam_pos.xyz;
+    result.position = r_data.proj * r_data.view * vec4<f32>(pos, 1.0);
+    return result;
+}
+
 struct EntityOutput {
     @builtin(position) position: vec4<f32>,
     @location(1) normal: vec3<f32>,
@@ -78,3 +104,15 @@ fn fs_entity(vertex: EntityOutput) -> @location(0) vec4<f32> {
     let reflected_color = textureSample(r_texture, r_sampler, reflected).rgb;
     return vec4<f32>(vec3<f32>(0.1) + 0.5 * reflected_color, 1.0);
 }
+
+@fragment
+fn fs_ground(vertex: GroundOutput) -> @location(0) vec4<f32> {
+    //let incident = normalize(vertex.view);
+    //let normal = normalize(vertex.normal+vec3<f32>(cos(vertex.pos.x)/16.0,0.0,sin(vertex.pos.z)/16.0));
+    //let reflected = incident - 2.0 * dot(normal, incident) * normal;
+
+    //let reflected_color = textureSample(r_texture, r_sampler, reflected).rgb;
+    //return vec4<f32>(vec3<f32>(0.1) + 0.5 * reflected_color, 1.0);
+    let dir = vec3<f32>(-1.0)+vec3<f32>(vertex.pos.x/16.%1.0,0.0,vertex.pos.z/16.%1.0)*2.0;
+    return vec4<f32>(textureSample(r_texture, r_sampler, dir).rgb, 1.0);
+}