Class: RBGL::Engine::Rasterizer::TriangleRenderer

Inherits:
Object
  • Object
show all
Defined in:
lib/rbgl/engine/rasterizer/triangle_renderer.rb

Instance Method Summary collapse

Constructor Details

#initialize(framebuffer, interpolator:, viewport_transform:, edge_function:) ⇒ TriangleRenderer

Returns a new instance of TriangleRenderer.



7
8
9
10
11
12
# File 'lib/rbgl/engine/rasterizer/triangle_renderer.rb', line 7

def initialize(framebuffer, interpolator:, viewport_transform:, edge_function:)
  @framebuffer = framebuffer
  @interpolator = interpolator
  @viewport_transform = viewport_transform
  @edge_function = edge_function
end

Instance Method Details

#rasterize(v0, v1, v2, fragment_shader, uniforms, state) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rbgl/engine/rasterizer/triangle_renderer.rb', line 14

def rasterize(v0, v1, v2, fragment_shader, uniforms, state)
  p0 = @viewport_transform.call(v0[:position])
  p1 = @viewport_transform.call(v1[:position])
  p2 = @viewport_transform.call(v2[:position])

  area = @edge_function.call(p0, p1, p2)
  return if area.abs < 1e-10
  return if culled?(area, state[:cull_mode])

  min_x, max_x, min_y, max_y = bounds(p0, p1, p2)
  inv_area = 1.0 / area

  (min_y..max_y).each do |y|
    (min_x..max_x).each do |x|
      weights = barycentric_weights(p0, p1, p2, x + 0.5, y + 0.5)
      next unless inside_triangle?(weights)

      screen_weights = weights.map { |weight| weight * inv_area }
      corrected_weights = @interpolator.perspective_correct_weights(
        [v0[:position], v1[:position], v2[:position]],
        screen_weights
      )
      depth = @interpolator.interpolate_depth([p0.z, p1.z, p2.z], corrected_weights)
      attributes = @interpolator.interpolate([v0, v1, v2], corrected_weights)

      shade_fragment(x, y, depth, attributes, fragment_shader, uniforms, state)
    end
  end
end