• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

excaliburjs / Excalibur / 14804036802

02 May 2025 09:58PM UTC coverage: 5.927% (-83.4%) from 89.28%
14804036802

Pull #3404

github

web-flow
Merge 5c103d7f8 into 0f2ccaeb2
Pull Request #3404: feat: added Graph module to Math

234 of 8383 branches covered (2.79%)

229 of 246 new or added lines in 1 file covered. (93.09%)

13145 existing lines in 208 files now uncovered.

934 of 15759 relevant lines covered (5.93%)

4.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/engine/Graphics/Context/render-target.ts
1
import { RenderSource } from './render-source';
2

3
declare global {
4
  interface WebGL2RenderingContext {
5
    /**
6
     * Experimental only in chrome
7
     */
8
    drawingBufferFormat?: number;
9
  }
10
}
11

12
export interface RenderTargetOptions {
13
  gl: WebGL2RenderingContext;
14
  width: number;
15
  height: number;
16
  transparency: boolean;
17
  /**
18
   * Optionally enable render buffer multisample anti-aliasing
19
   *
20
   * By default false
21
   */
22
  antialias?: boolean;
23
  /**
24
   * Optionally specify number of anti-aliasing samples to use
25
   *
26
   * By default the max for the platform is used if antialias is on.
27
   */
28
  samples?: number;
29
}
30

31
export class RenderTarget {
32
  width: number;
33
  height: number;
34
  transparency: boolean;
UNCOV
35
  antialias: boolean = false;
×
UNCOV
36
  samples: number = 1;
×
37
  private _gl: WebGL2RenderingContext;
38
  public readonly bufferFormat: number;
39
  constructor(options: RenderTargetOptions) {
UNCOV
40
    this._gl = options.gl;
×
UNCOV
41
    this.width = options.width;
×
UNCOV
42
    this.height = options.height;
×
UNCOV
43
    this.transparency = options.transparency;
×
UNCOV
44
    this.antialias = options.antialias ?? this.antialias;
×
UNCOV
45
    this.samples = options.samples ?? this._gl.getParameter(this._gl.MAX_SAMPLES);
×
46

UNCOV
47
    const gl = this._gl;
×
48
    // Determine current context format for blitting later needs to match
UNCOV
49
    if (gl.drawingBufferFormat) {
×
50
      this.bufferFormat = gl.drawingBufferFormat;
×
51
    } else {
52
      // Documented in webgl spec
53
      // https://registry.khronos.org/webgl/specs/latest/1.0/
UNCOV
54
      if (this.transparency) {
×
UNCOV
55
        this.bufferFormat = gl.RGBA8;
×
56
      } else {
UNCOV
57
        this.bufferFormat = gl.RGB8;
×
58
      }
59
    }
60

UNCOV
61
    this._setupRenderBuffer();
×
UNCOV
62
    this._setupFramebuffer();
×
63
  }
64

65
  setResolution(width: number, height: number) {
UNCOV
66
    const gl = this._gl;
×
UNCOV
67
    this.width = width;
×
UNCOV
68
    this.height = height;
×
69

70
    // update backing texture size
UNCOV
71
    gl.bindTexture(gl.TEXTURE_2D, this._frameTexture);
×
UNCOV
72
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
×
73

74
    // update render buffer size
UNCOV
75
    if (this._renderBuffer) {
×
UNCOV
76
      gl.bindRenderbuffer(gl.RENDERBUFFER, this._renderBuffer);
×
UNCOV
77
      gl.renderbufferStorageMultisample(
×
78
        gl.RENDERBUFFER,
79
        Math.min(this.samples, gl.getParameter(gl.MAX_SAMPLES)),
80
        this.bufferFormat,
81
        this.width,
82
        this.height
83
      );
84
    }
85
  }
86

87
  private _renderBuffer!: WebGLRenderbuffer;
88
  public get renderBuffer() {
UNCOV
89
    return this._renderBuffer;
×
90
  }
91
  private _renderFrameBuffer!: WebGLFramebuffer;
92
  public get renderFrameBuffer() {
UNCOV
93
    return this._renderFrameBuffer;
×
94
  }
95

96
  private _frameBuffer!: WebGLFramebuffer;
97
  public get frameBuffer() {
UNCOV
98
    return this._frameBuffer;
×
99
  }
100
  private _frameTexture!: WebGLTexture;
101
  public get frameTexture() {
102
    return this._frameTexture;
×
103
  }
104

105
  private _setupRenderBuffer() {
UNCOV
106
    if (this.antialias) {
×
UNCOV
107
      const gl = this._gl;
×
108
      // Render buffers can be used as an input to a shader
UNCOV
109
      this._renderBuffer = gl.createRenderbuffer()!;
×
UNCOV
110
      this._renderFrameBuffer = gl.createFramebuffer()!;
×
UNCOV
111
      gl.bindRenderbuffer(gl.RENDERBUFFER, this._renderBuffer);
×
UNCOV
112
      gl.renderbufferStorageMultisample(
×
113
        gl.RENDERBUFFER,
114
        Math.min(this.samples, gl.getParameter(gl.MAX_SAMPLES)),
115
        this.bufferFormat,
116
        this.width,
117
        this.height
118
      );
UNCOV
119
      gl.bindFramebuffer(gl.FRAMEBUFFER, this._renderFrameBuffer);
×
UNCOV
120
      gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this._renderBuffer);
×
121
    }
122
  }
123

124
  private _setupFramebuffer() {
125
    // Allocates frame buffer
UNCOV
126
    const gl = this._gl;
×
UNCOV
127
    this._frameTexture = gl.createTexture()!;
×
UNCOV
128
    gl.bindTexture(gl.TEXTURE_2D, this._frameTexture);
×
UNCOV
129
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
×
130

131
    // set the filtering so we don't need mips
UNCOV
132
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
×
UNCOV
133
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
×
UNCOV
134
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
×
UNCOV
135
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
×
136

137
    // attach the texture as the first color attachment
UNCOV
138
    const attachmentPoint = gl.COLOR_ATTACHMENT0;
×
139

140
    // After this bind all draw calls will draw to this framebuffer texture
UNCOV
141
    this._frameBuffer = gl.createFramebuffer()!;
×
UNCOV
142
    gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
×
UNCOV
143
    gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, this._frameTexture, 0);
×
144

145
    // Reset after initialized
UNCOV
146
    this.disable();
×
147
  }
148

149
  public toRenderSource() {
UNCOV
150
    if (this.renderBuffer) {
×
151
      this.blitRenderBufferToFrameBuffer();
×
152
    }
UNCOV
153
    const source = new RenderSource(this._gl, this._frameTexture);
×
UNCOV
154
    return source;
×
155
  }
156

157
  public blitToScreen() {
UNCOV
158
    const gl = this._gl;
×
159
    // set to size of canvas's drawingBuffer
UNCOV
160
    if (this._renderBuffer) {
×
UNCOV
161
      gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.renderFrameBuffer);
×
UNCOV
162
      gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
×
UNCOV
163
      gl.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 1.0, 1.0]);
×
UNCOV
164
      gl.blitFramebuffer(0, 0, this.width, this.height, 0, 0, this.width, this.height, gl.COLOR_BUFFER_BIT, gl.LINEAR);
×
165
    } else {
UNCOV
166
      gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.frameBuffer);
×
UNCOV
167
      gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
×
UNCOV
168
      gl.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 1.0, 1.0]);
×
UNCOV
169
      gl.blitFramebuffer(0, 0, this.width, this.height, 0, 0, this.width, this.height, gl.COLOR_BUFFER_BIT, gl.LINEAR);
×
170
    }
171
  }
172

173
  public blitRenderBufferToFrameBuffer() {
UNCOV
174
    if (this._renderBuffer) {
×
UNCOV
175
      const gl = this._gl;
×
UNCOV
176
      gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.renderFrameBuffer);
×
UNCOV
177
      gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this.frameBuffer);
×
UNCOV
178
      gl.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 1.0, 1.0]);
×
UNCOV
179
      gl.blitFramebuffer(0, 0, this.width, this.height, 0, 0, this.width, this.height, gl.COLOR_BUFFER_BIT, gl.LINEAR);
×
180
    }
181
  }
182

183
  public copyToTexture(texture: WebGLTexture) {
UNCOV
184
    const gl = this._gl;
×
UNCOV
185
    if (this._renderBuffer) {
×
UNCOV
186
      this.blitRenderBufferToFrameBuffer();
×
187
    }
UNCOV
188
    gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
×
UNCOV
189
    gl.bindTexture(gl.TEXTURE_2D, texture);
×
UNCOV
190
    gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, this.width, this.height, 0);
×
191
  }
192

193
  /**
194
   * When called, all drawing gets redirected to this render target
195
   */
196
  public use() {
UNCOV
197
    const gl = this._gl;
×
UNCOV
198
    if (this.antialias) {
×
UNCOV
199
      gl.bindFramebuffer(gl.FRAMEBUFFER, this._renderFrameBuffer);
×
200
    } else {
UNCOV
201
      gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
×
202
    }
203

204
    // very important to set the viewport to the size of the framebuffer texture
UNCOV
205
    gl.viewport(0, 0, this.width, this.height);
×
206
  }
207

208
  /**
209
   * When called, all drawing is sent back to the canvas
210
   */
211
  public disable() {
UNCOV
212
    const gl = this._gl;
×
213
    // passing null switches rendering back to the canvas
UNCOV
214
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
×
UNCOV
215
    gl.bindTexture(gl.TEXTURE_2D, null);
×
216
  }
217
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc