pcbjam/tests/3d-regression/native/fbo_capture.h
Istvan Matejcsok ce1473c9ab test(3d): screenshot-baseline TDD suite for the 3D viewer OpenGL->WebGL port — 47 native goldens + red-state WebGL harness
tests/3d-regression mirrors the gal-regression pattern at renderer scale:
shared C++ scenarios call real KiCad 3D-viewer code (opengl_utils, display
lists + DrawCulled stencil subtraction, MODEL_3D VBOs, private generators via
a rob-template accessor, and full reload()+Redraw() composites over a
synthetic BOARD_ADAPTER). A native macOS harness renders them on real OpenGL
into 47 committed goldens (bit-deterministic, FBO capture); the wasm harness
compiles the same TUs against wasm/stubs/gl_ffp_stub.c no-ops so every
scenario renders blank — the TDD red state (parity meter: 47/47 changed).
Comparisons use the CI pixelmatch engine via the new generic compare-dirs.ts
(floors.json levels; manifest.json cmp-guards registry drift).

Documents an upstream bug: appendPostMachiningGeometry's countersink path
adds middle quads without normals, silently erasing the walls of any
display list it is batched into (3d-post-machining.png keeps the lists
separate to record it).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 15:45:58 +02:00

46 lines
1.2 KiB
C++

/**
* Offscreen FBO for deterministic fixed-size capture, mirroring
* EDA_3D_CANVAS::RenderToFrameBuffer (eda_3d_canvas.cpp:736-772):
* GL_RGBA8 color texture + GL_DEPTH24_STENCIL8 renderbuffer on
* GL_DEPTH_STENCIL_ATTACHMENT (the stencil is required by
* OPENGL_RENDER_LIST::DrawCulled hole cutting).
*
* Rendering into an FBO makes the output independent of window size and
* Retina scaling — pixels are exactly aWidth x aHeight.
*/
#ifndef FBO_CAPTURE_H
#define FBO_CAPTURE_H
#include <kicad_gl/kiglad.h>
#include <cstdint>
#include <vector>
class FBO_CAPTURE
{
public:
/// Create the FBO; returns false if the framebuffer is incomplete.
/// Falls back to the EXT entry points if the core ARB ones didn't load
/// (Apple GL 2.1 exposes both; glad loads by symbol name).
bool Create( int aWidth, int aHeight );
void Bind();
/// glFinish + glReadPixels(GL_RGBA); aOut is resized to w*h*4.
bool ReadPixels( std::vector<uint8_t>& aOut );
void Destroy();
int Width() const { return m_width; }
int Height() const { return m_height; }
private:
int m_width = 0;
int m_height = 0;
GLuint m_fbo = 0;
GLuint m_colorTexture = 0;
GLuint m_depthStencil = 0;
};
#endif // FBO_CAPTURE_H