Closed mjbartholomew closed 1 month ago
This is a difference of color space. Ebitengine uses kCGColorSpaceDisplayP3 and this might be different from other applications.
The expected result would be that the colors would appear the same in the app's window as they do in other applications (like Chrome, Safari, Slate, Preview)
What about Firefox?
Firefox is the same as Chrome and Safari. Here is a screenshot of the browsers in the following order: Firefox, Chrome, and Safari.
The content of the test file is:
<!DOCTYPE html>
<html>
<head>
<style>
body {
color: red;
background-color: #3b9030;
}
</style>
</head>
<body></body>
</html>
All 3 of the browsers display the same color for #3b9030. Consulting the Digital Color Meter app, when I hover over the pixels in each of the browser windows, it displays the decimal equivalent for #3b9030.
I wondered if colorspace played a part in this issue. I believe the browsers interpret CSS colors, as well as untagged images, as sRGB. Firefox made changes in version 89 to follow this approach.
OK so the differences are color spaces, and now all the modern browsers now adopt sRGB by default.
I don't think this is a bug in Ebitengine. Ebitengine is not responsible to output colors that are compatible with other applications.
Also, with OpenGL mode, there is no way to control color spaces and probably Display P3 is used. Ebitengine tries to emulate this with Metal for consistency. You can try it with EBITENGINE_GRAPHICS_LIBRARY=opengl go run path/to/your/game
.
Using EBITENGINE_GRAPHICS_LIBRARY=opengl go run path/to/your/game
made a difference, and the green color now renders correctly. Is there a way to bake this environment value into the binary? When I try EBITENGINE_GRAPHICS_LIBRARY=opengl go build
the resulting binary still produces the unexpected colors.
Or is it possible to add an option in Ebitengine to use the sRGB color profile for macOS (e.g. MTKView.colorPixelFormat = .bgra8Unorm_srgb)?
For those researching how to change the graphics library, you need to use ebiten.RunGameWithOptions()
instead of ebiten.RunGame()
ebiten.RunGameWithOptions()
has a second parameter, which takes a variable of type RunGameOptions
. The following is an example of how to create that variable (in this case, named op
), and make the change to the GraphicsLibrary value to select OpenGL.
op := &ebiten.RunGameOptions{}
op.GraphicsLibrary = ebiten.GraphicsLibraryOpenGL
Note: I have found that using GraphicsLibraryOpenGL on macOS does result in a less smooth experience, with frames dropping, when compared to using Metal.
Using EBITENGINE_GRAPHICS_LIBRARY=opengl go run path/to/your/game made a difference, and the green color now renders correctly.
That's odd. I got the same result with OpenGL and Metal. I'm using MacBook Pro 2020.
Also, the Metal version is not incorrect. This just uses a different color space than sRGB and some colors might not be able to be represented in sRGB.
Or is it possible to add an option in Ebitengine to use the sRGB color profile for macOS (e.g. MTKView.colorPixelFormat = .bgra8Unorm_srgb)?
I can consider this if you want, but as I said, this is not controllable when OpenGL is used.
Or is it possible to add an option in Ebitengine to use the sRGB color profile for macOS (e.g. MTKView.colorPixelFormat = .bgra8Unorm_srgb)?
I can consider this if you want, but as I said, this is not controllable when OpenGL is used.
As OpenGL has been deprecated by Apple in favor of Metal, I would greatly appreciate it if you would consider adding that as an option.
Using EBITENGINE_GRAPHICS_LIBRARY=opengl go run path/to/your/game made a difference, and the green color now renders correctly.
That's odd. I got the same result with OpenGL and Metal. I'm using MacBook Pro 2020.
Here are the results I have on my 2018 Mac mini (EBITENGINE_GRAPHICS_LIBRARY=opengl
on the right window):
Use CAMetalLayer
's colorSpace
property. Possible values are:
kCGColorSpaceDisplayP3
(The current default)kCGColorSpaceSRGB
kCGColorSpaceLinearSRGB
Use DXGI_OUTPUT_DESC1
's ColorSpace
member or IDXGISwapChain3::SetColorSpace1
. Possible values are:
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
(The standard sRGB?)How can we specify Display P3 for DirectX?
There is no standard way to specify a color space?
WebGLRenderingContext
's drawingBufferColorSpace
is available. This feature is experimental.
We need more investigation.
I failed to find a good solution for DirectX. Probably just ignoring the option would be fine.
Here is the result of an experimental option 'ColorSpace'. (sRGB vs DisplayP3)
Ebitengine Version
2.6.3
Operating System
Go Version (
go version
)go1.21.5 darwin/amd64
What steps will reproduce the problem?
Explicitly define the screen color via ebiten.Image.Fill()
As can be seen in the image under the "What happens instead?" section, it also impacts colors defined by images.
What is the expected result?
The expected result would be that the colors would appear the same in the app's window as they do in other applications (like Chrome, Safari, Slate, Preview)
What happens instead?
The colors are rendered differently. Using the Digital Color Meter on macOS, I can see that the color #3b9030 renders as expected in Safari, Chrome, Preview, and Slate, yet when displayed in an Ebitengine application window, I instead see #009219.
The top-half of the following image is from an app created with Ebitengine, whereas the bottom half is from the app Slate. As you can see, the colors are off when drawn by Ebitengine. Every channel (Red, Green, and Blue) have been altered, with the Red channel changing from 0x3b in the code to 0x00 on screen.
The brown block colors are also off, but just not as pronounced as can be seen with the green background color.
Anything else you feel useful to add?
No response