Comments (14)
As exposure and faintestMag are mutually convertible it doesn't matter what variable to use. But I think that for user convenience it's better to keep faintestMag.
from celestia.
Outdated. See original post for up-to-date information.
There is an even better solution for the last PSF design: you can calculate the square size depending on the brightness, in the range from 0.012° to 1.5°. For example, for br=1
angle is 0.25°.
def PSF_max_theta(br: float):
return 0.012 + 1.488 / (np.sqrt(br_limit * 10e6 / (11 * br)) + 1)
and changes in draw_fast()
:
# glare render on < 3°×3° field
square_half_size = ceil(PSF_max_theta(color0.max()) / degree_per_px)
Why not to calculate the square size for all the angles, not just in 3°?
- The original PSF fades out more slowly, square sizes would be much larger → less performance
- The original PSF has very different behavior at small and large angles. In any case, we will need a function that works specifically on small angles.
from celestia.
In the future, it may be necessary to link the “convenient linear brightness scale” to the physical one. Let me formalize how I introduce a “convenient scale”: the green color component for a 0 magnitude star illuminates exactly one pixel (exposure=1 everywhere). Let's link the zero magnitude to the Vegan spectrum from the CALSPEC database as a standard, and also assume that the green component of the pixel completely follows the green sensitivity curve of the eye. Correctly multiplying one curve by another, I obtain that the unit of the “convenient brightness scale” corresponds to 3.844750664631218e-11 W/m² in SI.
from celestia.
I have implemented the same in c++ and glsl - https://github.com/CelestiaProject/Celestia/pull/1952/files (windows artifacts at https://github.com/CelestiaProject/Celestia/actions/runs/6658496014).
Problems - square_half_size
is too large, in my tests Vega has > 500px. But both the bright star and glare are much smaller. Actually Vega has less than 10px core with the faintest magnitude set to 15. 99% of stars are just 1px. And when i make faintest magnitude higher, square_half_size should always grow, but around 12 it goes down.
from celestia.
What to do with the faintest apparent magnitude currently in use?
- Way 1: nothing, and calculate exposure for the new star style with
faintestMag2exposure
. - Way 2: completely replace
faintestMag
with exposure in the code, and support other star styles withexposure2faintestMag
. Perhaps introducing an exposure will help future developments.
br_limit = 1 / (255 * 12.92)
def faintestMag2exposure(faintestMag):
return br_limit * 10**(0.4*faintestMag)
def exposure2faintestMag(exposure):
return 2.5 * np.log10(exposure/br_limit)
from celestia.
Outdated. See original post for up-to-date information.
Improved design of optimized formulas:
- Render diameter increased from one degree to three
- The border will never be sharp
- The equations are even simpler (and faster)
def PSF_fast(theta: float):
""" Optimized formula of the human eye's point source function """
if theta < 0.02662:
return 1 - 53.6*theta + 760*theta*theta
elif theta < 1.5:
temp = 1.488 / (theta - 0.012) - 1 # 1.488+0.012=1.5, it's radius
return 1.1e-5 * temp * temp
else:
return 0
However, the large diameter is both an advantage and a disadvantage: now the renderer needs to draw 9 times more pixels. If there is a question of increasing performance, then for br0 < 40
you can use PSF_fast
from the first post.
from celestia.
It turned out that the function PSF_max_theta
did not work as expected: it returns 1.4999140248716338° even for 1 Vega, the square isn't actually cropped. Also, I tried to fix high (>100 Vega) brightnesses, and fixed them, but with no cropping squares too. I have an idea how to fix everything. However, the basic logic remains the same, so you can try to add to Celestia what I already wrote, and then update the functions when the experiments are successful.
from celestia.
After doing a little research, I was able to achieve a single optimized PSF work at any brightness, and, most importantly, that zeroes at an angle, determined from the brightness. Original post updated.
from celestia.
I used two methods to reduce the square size:
- Formula coefficients were re-selected to reduce it by 1.75 times, but accuracy compared to the original PSF was slightly reduced too. (At the same time, the formula was further simplified and the overexposure radius was reduced)
- Cropping pixels below the minimum render brightness also reduced it by almost half. According to OpenGL Wiki: "Implementations are allowed to round the converted integer any way it likes". Therefore, the case of maximum radius was considered, i.e. regular rounding (hopefully no OpenGL implementation uses a ceil rounding, that would be weird).
The code became like this:
def PSF_square(theta: float, min_theta: float, max_theta: float, k: float):
"""
Human eye's point source function, optimized to fit a square.
Lower limit on brightness and angular size: 1 Vega and 0.05 degrees per pixel. No upper limits.
"""
if theta < min_theta:
return 1 # overexposed
elif theta < max_theta:
brackets = max_theta / theta - 1
return k * brackets * brackets
else:
return 0 # after max_theta function starts to grow again
# Option 2: glare square render
max_br = color0.max()
max_theta = 0.2 * np.sqrt(max_br) # glare radius
k = 3.3e-5 * max_theta**-2.5 # common constant, depending originally on star brightness
min_theta = max_theta / (k**-0.5 + 1)
square_half_size = floor(max_theta / (np.sqrt(0.5 * br_limit / (k * max_br)) + 1) / degree_per_px)
...
color = color0 * PSF_square(theta, min_theta, max_theta, k)
from celestia.
For too bright objects, e.g. the Sun when we are inside the Solar system, core is HUGE (radius is something around 1000).
Now glare radius is too small so the image is squary (Sirius at ~1ly with faintest mag = 15):
The star is just a fade pixel.
At 2.80 it disappears. And appears back at 2.60 - when another branch is executed (for 1px stars).
from celestia.
some thoughts.
in magnitude range from [faintestMag; faintestMag-N], where N is 3 or 4, start is 1 px, with brightness increasing from 1/255 to 1.0.
in (faintestMag-N; faintestMag-M], where M>N, only radius grows. glare is absent (radius == star radius).
in (faintestMag-M; -inf) radius grows but glare radius grows faster.
taking into account limited point sizes and that inside solar systems suns are too bright, at some faintestMag-P, where P > M, radii should grow much slower.
from celestia.
It's possible, but there are many problems. The main one is it’s difficult to make the “blur” and “radius” functions visually pleasing. The transition will be sharp and noticeable. Also, for gamma correction, the function must very smoothly go to limited zero. Polynomials will not work, nor will exponential.
I think the current implementation is one of the most optimal possible for glowing within a few tens to hundreds of pixels, but the high brightness problem is real. What about, as soon as a star with a magnitude higher than P appears in the field of view, to force the magnitude limit so as never to exceed P?
from celestia.
What about, as soon as a star with a magnitude higher than P appears in the field of view, to force the magnitude limit so as never to exceed P?
Sounds ok for me
from celestia.
There is another optimization that (for now) can significantly reduce the size of the square: to determine the br_limit
depending on the gamma correction.
if srgb:
br_limit = 1 / (255 * 12.92)
else:
br_limit = 1 / 255
from celestia.
Related Issues (20)
- Strating celestia-qt with URL crashes the program HOT 2
- Many question marks in Chinese enviroment HOT 2
- The pronunciation of Celestia
- Very distant objects don't display
- Pre-Windows 10 1903 versions of ICU HOT 2
- [Win32] Goto Object dialog ignores zeroes
- [Qt] Barycenters in star browser HOT 1
- CI: MacOS front-ends HOT 2
- setlocale is not thread safe, causing crash due to race HOT 2
- Classic star colors HOT 1
- Incorrect contexted string extracted from windows RC files
- Dubious test in shadermanager.cpp
- Could not read star database HOT 2
- Wasted data for ring systems
- Recent GTK changes cause build error HOT 6
- segfault when exiting celestia (qt5/qt6)
- std::binary_function is (deprecated in C++11) and (removed in C++17) HOT 1
- `ApplyShadow` result discarded during shader creation HOT 1
- Constellation lines beyond Solar System
- HUD translation contexts HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from celestia.