'MetalKit view MTKView showing blurry stroke and extrapolating their designated path/size
I'm trying to plot squares using MetalKit. Each square has an origin and a size, like this:
Origin:
▿ (204.5746214852199, 62.83450704225352)
- x : 204.5746214852199
- y : 62.83450704225352
Size:
▿ (1.4612472963229992, 1.4612676056338028)
- width : 1.4612472963229992
- height : 1.4612676056338028
The problem is that when MetalKit draws those, each square is drawn a different weird way that exceeds the expected area and shape for what a square should look like (see image below) - yes, each red cluster should represent a single 1x1 square of the same size of those grey squares underneath. Furthermore, its borders are also blurry (this is a zoomed in image). I am using this sampler:
constexpr sampler textureSampler(mag_filter::nearest,
min_filter::nearest);
In the image above, the greyscale squares is what each red square should be fitting to (their borders and exact position).
Any clue how to achieve this? Could MetalKit be losing decimal precision along the way? How can I make the squares edges sharp?
Here's my vertices function and position struct: https://github.com/s1ddok/MetalCoreGraphics/blob/d32c680a156548e20e9e9deb06e14cc260bcdea1/MetalCoreGraphics/Shaders.metal#L12-L30
Any leads would be super helpful here! Appreciate it!
Solution 1:[1]
According to the Metal Shader Language Specification Metal stores the position values of Vertex in single-precision floating-point format.
Type | Description |
---|---|
float | A 32-bit floating-point. The float data type must conform to the IEEE 754 single precision storage format. |
This works well for small values, which it can represent precisely, but precision decreases as values increase because of floating-point rounding errors. As a result, Actor rendered far from the origin aren't positioned accurately (they're slightly misplaced).
Solution 2:[2]
I'd suggest you debug the fragment that looks incorrect through https://developer.apple.com/documentation/metal/developing_and_debugging_metal_shaders You'll be able to check what computation is being done for each output fragment and whether it is unexpected.
Solution 3:[3]
One way would be to to utilise the fact that you can pass in certain props to text fields and combine this with regex. This wouldn't necessarily prevent them from allowing it to be entered, however, it will prevent submission of the text field if it contains any numbers. You would then just need to add error handling to display the associated message
<TextField
inputProps={{ pattern: "([^0-9]*)" }} error={'Error Message'}
/>
Check out the textfield api here for further details
Solution 4:[4]
Instead of re-inventing the wheel you could use something like react-number-format
.
They have an example in their docs:
<NumberFormat customInput={TextField} format="#### #### #### ####" />
It is also possible to do it the other way around, giving more control over the TextField
but needs a bit more work.
import React from "react";
import { InputBaseComponentProps } from "@mui/material";
import NumberFormat from "react-number-format";
export const NumberInput = React.forwardRef<
NumberFormat,
InputBaseComponentProps
>((props, ref) => {
const { onChange, ...other } = props;
return (
<NumberFormat
isNumericString
{...(other as any)}
getInputRef={ref}
onValueChange={(values) =>
onChange && onChange({ target: { value: values.value } } as any)
}
/>
);
});
Then use it like this, note that the price
value is still a string.
const [price, setPrice] = useState("0");
return <TextField
value={price}
onChange={(evt) => setPrice(evt.target.value) }
InputProps={{
inputComponent: NumberInput,
inputProps: {
decimalSeparator: ",",
decimalScale: 2,
fixedDecimalScale: true,
allowNegative: false,
prefix: "€ ",
},
}}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Hamid Yusifli |
Solution 2 | Ceylo |
Solution 3 | Liukaku |
Solution 4 | Jan Misker |