1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-27 15:29:34 +00:00

Adds adjustment for display aspect ratio.

While also realising that I appear to be getting away without an MTLVertexDescriptor for Scans. Maybe OpenGL has prejudiced me, and they're actually optional for interleaved data?
This commit is contained in:
Thomas Harte 2020-08-07 22:29:24 -04:00
parent fbda7aab23
commit 38960a08d6
2 changed files with 20 additions and 13 deletions

View File

@ -16,6 +16,7 @@ namespace {
struct Uniforms { struct Uniforms {
int32_t scale[2]; int32_t scale[2];
float lineWidth; float lineWidth;
float aspectRatioMultiplier;
}; };
constexpr size_t NumBufferedScans = 2048; constexpr size_t NumBufferedScans = 2048;
@ -33,6 +34,9 @@ constexpr size_t NumBufferedScans = 2048;
id<MTLBuffer> _quadBuffer; // i.e. four vertices defining a quad. id<MTLBuffer> _quadBuffer; // i.e. four vertices defining a quad.
id<MTLBuffer> _uniformsBuffer; id<MTLBuffer> _uniformsBuffer;
id<MTLBuffer> _scansBuffer; id<MTLBuffer> _scansBuffer;
// Current uniforms.
Uniforms _uniforms;
} }
- (nonnull instancetype)initWithView:(nonnull MTKView *)view { - (nonnull instancetype)initWithView:(nonnull MTKView *)view {
@ -51,11 +55,11 @@ constexpr size_t NumBufferedScans = 2048;
// Allocate space for uniforms. // Allocate space for uniforms.
_uniformsBuffer = [view.device newBufferWithLength:16 options:MTLResourceCPUCacheModeWriteCombined]; _uniformsBuffer = [view.device newBufferWithLength:16 options:MTLResourceCPUCacheModeWriteCombined];
const Uniforms testUniforms = { _uniforms.scale[0] = 1024;
.scale = {1024, 1024}, _uniforms.scale[1] = 1024;
.lineWidth = 1.0f / 312.0f _uniforms.lineWidth = 1.0f / 312.0f;
}; _uniforms.aspectRatioMultiplier = 1.0f;
[self setUniforms:testUniforms]; [self setUniforms];
// Allocate a large buffer for scans. // Allocate a large buffer for scans.
_scansBuffer = [view.device _scansBuffer = [view.device
@ -70,7 +74,7 @@ constexpr size_t NumBufferedScans = 2048;
vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2; vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2;
vertexDescriptor.layouts[0].stride = sizeof(float)*2; vertexDescriptor.layouts[0].stride = sizeof(float)*2;
// Create a scans buffer, and for now just put two in there. // TODO: shouldn't I need to explain the Scan layout, too? Or do these things not need to be specified when compatible?
// Generate TEST pipeline. // Generate TEST pipeline.
id<MTLLibrary> library = [view.device newDefaultLibrary]; id<MTLLibrary> library = [view.device newDefaultLibrary];
@ -85,8 +89,8 @@ constexpr size_t NumBufferedScans = 2048;
return self; return self;
} }
- (void)setUniforms:(const Uniforms &)uniforms { - (void)setUniforms {
memcpy(_uniformsBuffer.contents, &uniforms, sizeof(Uniforms)); memcpy(_uniformsBuffer.contents, &_uniforms, sizeof(Uniforms));
} }
- (void)setTestScans { - (void)setTestScans {
@ -112,8 +116,8 @@ constexpr size_t NumBufferedScans = 2048;
@param size New drawable size in pixels @param size New drawable size in pixels
*/ */
- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size { - (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {
// I think (?) I don't care about this; the MKLView has already handled resizing the backing, _uniforms.aspectRatioMultiplier = float((4.0 / 3.0) / (size.width / size.height));
// which will naturally change the viewport. [self setUniforms];
} }
/*! /*!

View File

@ -17,8 +17,11 @@ struct Uniforms {
// for mapping from scan-style integer positions into eye space. // for mapping from scan-style integer positions into eye space.
int2 scale [[attribute(0)]]; int2 scale [[attribute(0)]];
// This provides the intended width of a scan, in eye-coordinate terms. // This provides the intended height of a scan, in eye-coordinate terms.
float lineWidth [[attribute(1)]]; float lineWidth [[attribute(1)]];
// Provides a scaling factor in order to preserve 4:3 central content.
float aspectRatioMultiplier [[attribute(2)]];
}; };
// This is intended to match `Scan` as defined by the BufferingScanTarget. // This is intended to match `Scan` as defined by the BufferingScanTarget.
@ -53,7 +56,7 @@ vertex ColouredVertex scanVertexMain( QuadInputVertex vert [[stage_in]],
constant Uniforms &uniforms [[buffer(1)]], constant Uniforms &uniforms [[buffer(1)]],
constant Scan *scans [[buffer(2)]], constant Scan *scans [[buffer(2)]],
ushort instance [[instance_id]]) { ushort instance [[instance_id]]) {
// Unpack start and end vertices. // Unpack start and end vertices; little-endian numbers are assumed here.
const float2 start = float2( const float2 start = float2(
float(scans[instance].startPosition & 0xffff) / float(uniforms.scale.x), float(scans[instance].startPosition & 0xffff) / float(uniforms.scale.x),
float(scans[instance].startPosition >> 16) / float(uniforms.scale.y) float(scans[instance].startPosition >> 16) / float(uniforms.scale.y)
@ -70,7 +73,7 @@ vertex ColouredVertex scanVertexMain( QuadInputVertex vert [[stage_in]],
// Hence determine this quad's real shape. // Hence determine this quad's real shape.
ColouredVertex output; ColouredVertex output;
output.position = float4( output.position = float4(
(start + vert.position.x * tangent + vert.position.y * normal * uniforms.lineWidth) * float2(2.0, -2.0) + float2(-1.0, 1.0), ((start + vert.position.x * tangent + vert.position.y * normal * uniforms.lineWidth) * float2(2.0, -2.0) + float2(-1.0, 1.0)) * float2(uniforms.aspectRatioMultiplier, 1.0),
0.0, 0.0,
1.0 1.0
); );