Class: Doom::Render::HardwareRenderer

Inherits:
Renderer
  • Object
show all
Includes:
OpenGL
Defined in:
lib/doom/render/hardware_renderer.rb

Overview

GPU rasterizer hosted inside Gosu's OpenGL context. The initial backend renders real world triangles with perspective projection and depth test.

Direct Known Subclasses

RayTracingRenderer

Defined Under Namespace

Classes: Batch

Constant Summary collapse

ANIMATED_DECORATIONS =
%w[TBLU TGRN TRED SMIT COLU CAND CBRA].freeze
VERTEX_STRIDE =
8 * 4
MAX_LIGHTS =
8
STATIC_LIGHTS =
{
  44 => [0.25, 0.35, 1.0], 45 => [0.25, 1.0, 0.35],
  46 => [1.0, 0.22, 0.12], 34 => [1.0, 0.65, 0.22],
  35 => [1.0, 0.65, 0.22], 2028 => [1.0, 0.75, 0.35]
}.freeze

Constants inherited from Renderer

Renderer::SKY_TEXTUREMID, Renderer::SKY_XSCALE, Renderer::SKY_YSCALE

Instance Attribute Summary collapse

Attributes inherited from Renderer

#animations, #colormap, #combat, #cos_angle, #flats, #framebuffer, #hidden_things, #leveltime, #map, #monster_ai, #palette, #player_angle, #player_x, #player_y, #player_z, #players, #sin_angle, #skip_background_fill, #sprites, #textures, #view_player, #wad

Instance Method Summary collapse

Methods inherited from Renderer

#apply_view, #build_native_renderer, #check_plane, #draw_all_visplanes, #draw_floor_ceiling_background, #draw_sky_plane, #draw_span, #fill_uncovered_with_sector, #find_or_create_visplane, #native_wall_pass, #precompute_column_data, #render_visplane_spans, #set_player, #sprite_diagnostics

Constructor Details

#initializeHardwareRenderer

Returns a new instance of HardwareRenderer.



30
31
32
33
34
35
36
37
# File 'lib/doom/render/hardware_renderer.rb', line 30

def initialize(...)
  super
  @mesh = WorldMesh.new(@map, @textures)
  @geometry_signature = geometry_signature
  @gl_textures = {}
  @texture_dimensions = {}
  @gpu_batches = nil
end

Instance Attribute Details

#meshObject (readonly)

Returns the value of attribute mesh.



28
29
30
# File 'lib/doom/render/hardware_renderer.rb', line 28

def mesh
  @mesh
end

Instance Method Details

#draw_hardware(viewport_width, viewport_height) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/doom/render/hardware_renderer.rb', line 55

def draw_hardware(viewport_width, viewport_height)
  Gosu.gl do
    load_opengl_library
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_CULL_FACE)
    glCullFace(GL_BACK)
    glFrontFace(GL_CCW)
    glEnable(GL_TEXTURE_2D)
    glDepthFunc(GL_LEQUAL)
    glClearColor(0.025, 0.025, 0.04, 1.0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    draw_sky

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity
    aspect = viewport_width.to_f / viewport_height
    glFrustum(-1.0, 1.0, -1.0 / aspect, 1.0 / aspect, 1.0, 16_384.0)
    glMatrixMode(GL_MODELVIEW)
    glLoadMatrixf(view_matrix.pack('f16'))

    rebuild_gpu_batches if @gpu_batches.nil? || @gpu_batches_dirty
    setup_lighting

    # Invisible back faces must still occlude rooms when the camera is
    # outside the playable map, matching the classic BSP solid-wall clip.
    draw_occluder_depth_prepass
    glEnable(GL_CULL_FACE)

    draw_gpu_batches
    glDisable(GL_LIGHTING)
    glBindTexture(GL_TEXTURE_2D, 0)
    glDisable(GL_TEXTURE_2D)
    glDisable(GL_CULL_FACE)
    # Sprites should be depth-tested against walls, not sliced by the
    # floor they stand on. Preserve the color buffer, rebuild depth from
    # walls only, then draw billboarded things.
    glClear(GL_DEPTH_BUFFER_BIT)
    draw_occluder_depth_prepass(include_ceilings: true)
    draw_sprites
    capture_frame if ENV['DOOM_GL_CAPTURE'] && !@frame_captured
    glDisable(GL_DEPTH_TEST)
  end
end

#hardware?Boolean

Returns:



39
40
41
# File 'lib/doom/render/hardware_renderer.rb', line 39

def hardware?
  true
end

#render_frameObject

Simulation still calls render_frame; hardware drawing must happen from Window#draw, inside Gosu.gl, so only reset the compatibility framebuffer.



45
46
47
48
49
50
51
52
53
# File 'lib/doom/render/hardware_renderer.rb', line 45

def render_frame
  signature = geometry_signature
  if signature != @geometry_signature
    @mesh = WorldMesh.new(@map, @textures)
    @geometry_signature = signature
    @gpu_batches_dirty = true
  end
  @framebuffer.fill(0)
end