Commits

David Lin  committed 1a3ab6b

scattering!

  • Participants
  • Parent commits f6d30f2

Comments (0)

Files changed (8)

File data/assets/programs/debug.program.yml

+---
+:attribs: 
+  in_Position: 0
+:frag_datas:
+  fs_FragColor: 0
+:shaders:
+  - :type: :vertex
+    :code: |
+           #version 150 core
+           in vec4 in_Position;
+           out vec2 vs_TexCoord;
+           void main()
+           { // BEGIN
+             gl_Position = in_Position;
+             vs_TexCoord = in_Position.xy * 0.5 + 0.5;
+           } // END
+  - :type: :fragment
+    :code: |
+           #version 150 core
+           in vec2 vs_TexCoord;
+           out vec4 fs_FragColor;
+           uniform sampler2D s_Texture;
+           void main()
+           { // BEGIN
+             fs_FragColor = texture(s_Texture, vs_TexCoord);
+           } // END
+

File data/assets/programs/depth.program.yml

----
-:attribs: 
-  in_Position: 0
-:frag_datas:
-  fs_FragColor: 0
-:shaders:
-  - :type: :vertex
-    :file: cube_normal.vertex.glsl
-  - :type: :geometry
-    :file: cube_normal.geometry.glsl
-  - :type: :fragment
-    :code: |
-           #version 150 core
-           in vec3 gs_Position;
-           in vec3 gs_Normal;
-           out vec4 fs_FragColor;
-           void main()
-           { // BEGIN
-             fs_FragColor = vec4(gl_FragCoord.z);
-           } // END
-

File data/assets/programs/scattering.program (copy).yml

+---
+:attribs: 
+  in_Position: 0
+:frag_datas:
+  fs_FragColor: 0
+:shaders:
+  - :type: :vertex
+    :file: cube_normal.vertex.glsl
+  - :type: :geometry
+    :file: cube_normal.geometry.glsl
+  - :type: :fragment
+    :code: |
+           #version 150 core
+           uniform vec3 u_Albedo;
+           uniform vec3 u_Ks;
+           uniform float u_Ns;
+           uniform vec3 u_Light_Ka;
+           uniform vec3 u_Light_Kd;
+           uniform vec3 u_Light_Ks;
+           uniform vec3 u_Light_Pos;
+           uniform vec3 u_Light_SpotDir;
+           uniform float u_Light_SpotCosCutoff;
+           uniform mat4 u_Light_XfmFromView;
+           uniform sampler2D s_ShadowMap;
+           uniform float u_SSS_Strength;
+           in vec3 gs_Position;
+           in vec3 gs_Normal;
+           out vec4 fs_FragColor;
+           // distance
+           float distance(vec3 posV, vec3 normalV, int i) {
+             // Shrink the position to avoid artifacts on the silhouette
+             posV = posV - 0.005 * normalV;
+             // Transform to light space (from view space)
+             vec4 posL = u_Light_XfmFromView * vec4(posV, 1.0);
+             // Fetch depth from the shadow map
+             float d1 = texture(s_ShadowMap, posL.xy / posL.w).r;
+             float d2 = posL.z;
+             // Calculate the difference
+             return abs(d1 - d2);
+           } // END distance
+           // T function
+           vec3 T(float s) {
+             return vec3(0.233, 0.455, 0.648) * exp(-s * s / 0.0064) +
+                    vec3(0.1,   0.336, 0.344) * exp(-s * s / 0.0484) +
+                    vec3(0.118, 0.198, 0.0)   * exp(-s * s / 0.187)  +
+                    vec3(0.113, 0.007, 0.007) * exp(-s * s / 0.567)  +
+                    vec3(0.358, 0.004, 0.0)   * exp(-s * s / 1.99)   +
+                    vec3(0.078, 0.0,   0.0)   * exp(-s * s / 7.41);
+           } // END T
+           // entry point
+           void main()
+           { // BEGIN
+             // Light Vector (from point to light)
+             vec3 lv = normalize(u_Light_Pos - gs_Position);
+             // Half Vector (from point)
+             vec3 hv = normalize(lv + vec3(0,0,1));
+             // Ambient
+             vec3 ka = u_Albedo * u_Light_Ka;
+             // Diffuse
+             vec3 kd = u_Albedo * u_Light_Kd;
+             kd *= max(0, dot(gs_Normal, lv));
+             // Specular
+             vec3 ks = u_Ks * u_Light_Ks;
+             ks *= pow(max(0, dot(gs_Normal, hv)), u_Ns);
+             // Spot cutoff
+             float cut = dot(lv, -u_Light_SpotDir) - u_Light_SpotCosCutoff;
+             cut = max(0.0, sign(cut));
+             kd *= cut; ks *= cut;
+             // Scattering
+             // Calculate the distance traveled by the light inside of the object
+             float s = distance(gs_Position, gs_Normal) / u_SSS_Strength;
+             // Estimate the irradiance on the back
+             vec3 light = normalize(u_Light_Pos - gs_Position); // regular light vec
+             float irradiance = max(0.3 + dot(-gs_Normal, light), 0.0);
+             // Calculate transmitted light
+             vec3 transmittance = T(s) * u_Albedo * u_Light_Kd * cut * irradiance;
+             // Final
+             vec3 color = ka + kd + ks + transmittance;
+             fs_FragColor = vec4(color, 1.0);
+           } // END
+

File data/assets/programs/scattering.program.yml

            uniform vec3 u_Light_Pos;
            uniform vec3 u_Light_SpotDir;
            uniform float u_Light_SpotCosCutoff;
-           uniform mat4 u_Light_XfmFromView;
+           uniform mat4 u_LightFromView;
            uniform sampler2D s_ShadowMap;
            uniform float u_SSS_Strength;
            in vec3 gs_Position;
              // Shrink the position to avoid artifacts on the silhouette
              posV = posV - 0.005 * normalV;
              // Transform to light space (from view space)
-             vec4 posL = u_Light_XfmFromView * vec4(posV, 1.0);
+             vec4 posL = u_LightFromView * vec4(posV, 1.0);
+             posL.xy = posL.xy / posL.w * 0.5 + 0.5;
              // Fetch depth from the shadow map
-             float d1 = texture(s_ShadowMap, posL.xy / posL.w);
+             float d1 = texture(s_ShadowMap, posL.xy).r;
              float d2 = posL.z;
              // Calculate the difference
              return abs(d1 - d2);
            // entry point
            void main()
            { // BEGIN
-             // Light Vector (from point to light)
-             vec3 lv = normalize(u_Light_Pos - gs_Position);
-             // Half Vector (from point)
-             vec3 hv = normalize(lv + vec3(0,0,1));
-             // Ambient
-             vec3 ka = u_Albedo * u_Light_Ka;
-             // Diffuse
-             vec3 kd = u_Albedo * u_Light_Kd;
-             kd *= max(0, dot(gs_Normal, lv));
-             // Specular
-             vec3 ks = u_Ks * u_Light_Ks;
-             ks *= pow(max(0, dot(gs_Normal, hv)), u_Ns);
-             // Spot cutoff
-             float cut = dot(lv, -u_Light_SpotDir) - u_Light_SpotCosCutoff;
-             cut = max(0.0, sign(cut));
-             kd *= cut; ks *= cut;
              // Scattering
              // Calculate the distance traveled by the light inside of the object
              float s = distance(gs_Position, gs_Normal) / u_SSS_Strength;
              vec3 light = normalize(u_Light_Pos - gs_Position); // regular light vec
              float irradiance = max(0.3 + dot(-gs_Normal, light), 0.0);
              // Calculate transmitted light
-             vec3 transmittance = T(s) * u_Albedo * u_Light_Kd * cut * irradiance;
+             vec3 transmittance = T(s) * u_Albedo * u_Light_Kd * irradiance;
              // Final
-             vec3 color = /*ka + kd + ks +*/ transmittance;
+             vec3 color = transmittance;
              fs_FragColor = vec4(color, 1.0);
            } // END
 

File data/assets/programs/shadow_map.program.yml

+---
+:attribs: 
+  in_Position: 0
+:frag_datas:
+  fs_FragColor: 0
+:shaders:
+  - :type: :vertex
+    :file: cube_normal.vertex.glsl
+  - :type: :geometry
+    :file: cube_normal.geometry.glsl
+  - :type: :fragment
+    :code: |
+           #version 150 core
+           uniform mat4 u_Projection;
+           in vec3 gs_Position;
+           in vec3 gs_Normal;
+           out vec4 fs_FragColor;
+           void main()
+           { // BEGIN
+             vec4 pos = u_Projection * vec4(gs_Position, 1.0);
+             fs_FragColor = vec4(pos.z);
+           } // END
+

File data/assets/programs/shadowing.program.yml

+---
+:attribs: 
+  in_Position: 0
+:frag_datas:
+  fs_FragColor: 0
+:shaders:
+  - :type: :vertex
+    :file: cube_normal.vertex.glsl
+  - :type: :geometry
+    :file: cube_normal.geometry.glsl
+  - :type: :fragment
+    :code: |
+           #version 150 core
+           uniform vec3 u_Albedo;
+           uniform sampler2D s_ShadowMap;
+           uniform mat4 u_LightFromView;
+           in vec3 gs_Position;
+           in vec3 gs_Normal;
+           out vec4 fs_FragColor;
+           void main()
+           { // BEGIN
+             // Shadow
+             vec4 lpos = u_LightFromView * vec4(gs_Position, 1.0);
+             vec2 lcoord = lpos.xy / lpos.w * 0.5 + 0.5;
+             //fs_FragColor = lpos; return;
+             float z1 = texture(s_ShadowMap, lcoord).r;
+             float z2 = lpos.z - 0.01;
+             //fs_FragColor = vec4(z2); return;
+             if (z1 <= z2)
+               discard;
+             // Final 
+             fs_FragColor = vec4(u_Albedo, 1.0);
+           } // END
+
     @render[:light_proj] = Matrix3D.perspective @render[:light_cut_angle], 1.0,
                                                 @render[:light_znear],
                                                 @render[:light_zfar]
+    @render[:b_scatter] = true
+    @render[:b_light] = true
   end
   
   def display
     end
   end
   
+  def keyboard(key, x, y)
+    case key.chr
+    when 's'
+      @render[:b_scatter] = !@render[:b_scatter]
+      glutPostRedisplay()
+    when 'l'
+      @render[:b_light] = !@render[:b_light]
+      glutPostRedisplay()
+    end
+  end
+  
 end
     self.extend gl
     @parameters = {}
     
+    @quad = My::Quad.new(gl).tap do |g| g.prepare end
     @geom = My::Cube.new(gl).tap do |g| g.prepare end
-    @program = My::Program.new(gl).tap do |program|
+    @program_lighting = My::Program.new(gl).tap do |program|
       program.prepare 'plastic'
     end
+    @program_scattering = My::Program.new(gl).tap do |program|
+      program.prepare 'scattering'
+    end
+    @program_shadow = My::Program.new(gl).tap do |program|
+      program.prepare 'shadow_map'
+    end
+    @program_debug = My::Program.new(gl).tap do |program|
+      program.prepare 'debug'
+    end
+    
+    @shadow_map_tex = glGenTextures(1)[0]
+    @shadow_map_fbo = glGenFramebuffers(1)[0]
+    @shadow_map_rbo = glGenRenderbuffers(1)[0]
+    @shadow_map_size = 1024
     
+    glBindTexture GL_TEXTURE_2D, @shadow_map_tex
+    glTexImage2D GL_TEXTURE_2D, 0, GL_R32F, 1024, 1024,
+                 0, GL_RED, GL_FLOAT, nil
+    glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR
+    glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
+    glBindRenderbuffer GL_RENDERBUFFER, @shadow_map_rbo
+    glRenderbufferStorage GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, 1024, 1024
+    glBindFramebuffer GL_FRAMEBUFFER, @shadow_map_fbo
+    glFramebufferTexture2D GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                           GL_TEXTURE_2D, @shadow_map_tex, 0
+    glFramebufferRenderbuffer GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                              GL_RENDERBUFFER, @shadow_map_rbo
+    puts glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE
   end
   
   def [](key)
     prog.set_3f 'u_Light_Pos', (self[:view] * self[:light_pos])
     prog.set_3f 'u_Light_SpotDir', (self[:view] * self[:light_dir]).normalize
     prog.set_1f 'u_Light_SpotCosCutoff', Math.cos(self[:light_cut_angle])
-    prog.set_1f 'u_SSS_Strength', 1.0
+    prog.set_1f 'u_SSS_Strength', 100.0
     prog.set_1i 's_ShadowMap', 0
-    #light_xfm_from_view = @light_proj * self[:inverse_view]
-    #prog.set_matrix_4x4f 'u_Light_XfmFromView', light_xfm_from_view
   end
   
   def draw
     glEnable GL_DEPTH_TEST
     glEnable GL_CULL_FACE
     
-    # Display Back Buffer
-    #glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0)
-    #glDrawBuffer(GL_BACK)
-    #glViewport(0, 0, self[:window_width], self[:window_height])
+    # RenderTarget: Shadow FBO
+    glBindFramebuffer GL_DRAW_FRAMEBUFFER, @shadow_map_fbo
+    glDrawBuffer GL_COLOR_ATTACHMENT0
+    glViewport(0, 0, @shadow_map_size, @shadow_map_size)
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
     
-    @program.tap do |prog|
+    glDepthFunc GL_LESS
+    glDisable GL_BLEND
+    
+    @program_shadow.tap do |prog|
       glUseProgram(prog.id)
       update_uniform(prog)
+      prog.set_matrix_4x4f 'u_Projection', self[:light_proj]
+      prog.set_matrix_4x4f 'u_ModelView', light_lookat * self[:world]
     end
-   
-    @geom.bind_vertex_attrib 
+    
+    @geom.bind_vertex_attrib
     @geom.draw
     
+    # Bind Texture
+    glActiveTexture GL_TEXTURE0
+    glBindTexture GL_TEXTURE_2D, @shadow_map_tex
+    
+    # RenderTarget: Back Buffer
+    glBindFramebuffer GL_DRAW_FRAMEBUFFER, 0
+    glDrawBuffer GL_BACK
+    glViewport(0, 0, self[:window_width], self[:window_height])
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+    
+    # debug draw
+    if false
+      glUseProgram @program_debug.id
+      @quad.bind_vertex_attrib
+      @quad.draw
+      return
+    end
+    
+    glDepthFunc GL_LEQUAL
+    glEnable GL_BLEND
+    glBlendFunc GL_ONE, GL_ONE
+    
+    if self[:b_light]
+      @program_lighting.tap do |prog|
+        glUseProgram(prog.id)
+        update_uniform(prog)
+      end
+      @geom.bind_vertex_attrib 
+      @geom.draw
+    end
+    
+    if self[:b_scatter]
+      @program_scattering.tap do |prog|
+        glUseProgram(prog.id)
+        update_uniform(prog)
+        light_mat = self[:light_proj] * light_lookat * self[:inverse_view]
+        prog.set_matrix_4x4f 'u_LightFromView', light_mat
+      end
+      @geom.bind_vertex_attrib 
+      @geom.draw
+    end
   end
   
 end