• Log InLog In
  • Register
Liquid`
Team Liquid Liquipedia
EST 13:04
CET 19:04
KST 03:04
  • Home
  • Forum
  • Calendar
  • Streams
  • Liquipedia
  • Features
  • Store
  • EPT
  • TL+
  • StarCraft 2
  • Brood War
  • Smash
  • Heroes
  • Counter-Strike
  • Overwatch
  • Liquibet
  • Fantasy StarCraft
  • TLPD
  • StarCraft 2
  • Brood War
  • Blogs
Forum Sidebar
Events/Features
News
Featured News
ByuL: The Forgotten Master of ZvT29Behind the Blue - Team Liquid History Book19Clem wins HomeStory Cup 289HomeStory Cup 28 - Info & Preview13Rongyi Cup S3 - Preview & Info8
Community News
Team Liquid Map Contest - Preparation Notice0Weekly Cups (Feb 23-Mar 1): herO doubles, 2v2 bonanza1Weekly Cups (Feb 16-22): MaxPax doubles0Weekly Cups (Feb 9-15): herO doubles up2ACS replaced by "ASL Season Open" - Starts 21/0258
StarCraft 2
General
How do you think the 5.0.15 balance patch (Oct 2025) for StarCraft II has affected the game? ByuL: The Forgotten Master of ZvT Nexon's StarCraft game could be FPS, led by UMS maker Team Liquid Map Contest - Preparation Notice Weekly Cups (Feb 23-Mar 1): herO doubles, 2v2 bonanza
Tourneys
PIG STY FESTIVAL 7.0! (19 Feb - 1 Mar) RSL Season 4 announced for March-April Sparkling Tuna Cup - Weekly Open Tournament SEL Doubles (SC Evo Bimonthly) WardiTV Team League Season 10
Strategy
Custom Maps
Publishing has been re-enabled! [Feb 24th 2026] Map Editor closed ?
External Content
The PondCast: SC2 News & Results Mutation # 515 Together Forever Mutation # 514 Ulnar New Year Mutation # 513 Attrition Warfare
Brood War
General
BW General Discussion It's March 3rd BGH Auto Balance -> http://bghmmr.eu/ CasterMuse Youtube Recent recommended BW games
Tourneys
[Megathread] Daily Proleagues BWCL Season 64 Announcement The Casual Games of the Week Thread [LIVE] [S:21] ASL Season Open Day 1
Strategy
Soma's 9 hatch build from ASL Game 2 Fighting Spirit mining rates Simple Questions, Simple Answers Zealot bombing is no longer popular?
Other Games
General Games
Nintendo Switch Thread Battle Aces/David Kim RTS Megathread Diablo 2 thread Path of Exile Online Quake Live Config Editor Tool
Dota 2
The Story of Wings Gaming Official 'what is Dota anymore' discussion
League of Legends
Heroes of the Storm
Simple Questions, Simple Answers Heroes of the Storm 2.0
Hearthstone
Deck construction bug Heroes of StarCraft mini-set
TL Mafia
Mafia Game Mode Feedback/Ideas Vanilla Mini Mafia TL Mafia Community Thread
Community
General
US Politics Mega-thread Things Aren’t Peaceful in Palestine Russo-Ukrainian War Thread UK Politics Mega-thread NASA and the Private Sector
Fan Clubs
The IdrA Fan Club
Media & Entertainment
[Req][Books] Good Fantasy/SciFi books [Manga] One Piece Anime Discussion Thread
Sports
2024 - 2026 Football Thread Formula 1 Discussion TL MMA Pick'em Pool 2013
World Cup 2022
Tech Support
Laptop capable of using Photoshop Lightroom?
TL Community
The Automated Ban List
Blogs
Just Watchers: Why Some Only…
TrAiDoS
Unintentional protectionism…
Uldridge
ASL S21 English Commentary…
namkraft
Life Update and thoughts.
FuDDx
How do archons sleep?
8882
Customize Sidebar...

Website Feedback

Closed Threads



Active: 2049 users

A little excercise in optimization and math

Blogs > fmod
Post a Reply
fmod
Profile Blog Joined November 2013
Cayman Islands330 Posts
Last Edited: 2014-03-08 01:35:44
March 08 2014 01:35 GMT
#1
Today I was reading some code for atmospheric lighting. Glancing over the code, I noticed this: (I did rename a couple of things).

+ Show Spoiler +
// As the y tex coord goes from 0 to 1, the angle goes from 0 to 180 degrees
float fCos = 1 - (nAngle + nAngle) / (float)mHeight;
float fAngle = std::acos(fCos);
vec3 ray(std::sin(fAngle), std::cos(fAngle), 0);

for(int nHeight=0; nHeight < nSize; nHeight++)
{
// As the x tex coord goes from 0 to 1, the height goes from the bottom of the atmosphere to the top
float fHeight = delta + innerRadius + ((outerRadius - innerRadius) * nHeight) / mWidth;

// The position of the camera
vec3 eyepos(0, fHeight, 0);

// If the ray from vPos heading in the vRay direction intersects the inner
// radius (i.e. the planet), then this spot is not visible from the viewpoint
float B = 2.0f * dot(eyepos, ray);
float Bsq = B * B;
float Cpart = dot(eyepos, eyepos);
float C = Cpart - innerRadius*innerRadius;
float discr = Bsq - 4.0f * C;
bool bVisible = (fDet < 0 || (0.5f * (-B - std::sqrt(discr)) <= 0) && (0.5f * (-B + std::sqrt(discr)) <= 0));


What it does is pretty obvious, first it finds some cosine and sine to a particular angle, then applies the quadratic formula to solve the intersection of a ray with the planet.
If you know something about trigonometry, this will bother you a lot :

float fAngle = acosf(fCos);
vec3 ray(std::sin(fAngle), std::cos(fAngle), 0);

It does seem a little strange to call an inverse cosine only to take it's cosine again the next instruction, and of course we can replace it by fCos.
Secondly, we can eliminate the acos call entirely by using the pythagorean identity :

[image loading]
you can easily see how you can solve this to get sin(angle)

float fCos = 1 - (nAngle + nAngle) / (float)mHeight;
vec3 ray(std::sqrt(1 - fCos*fCos), fCos, 0);


secondly is the quadratic formula, to solve the intersection of the ray with the sphere. What most people forget to do is to remove all the 2, 4, 0.5 coefficients which will cancel each other anyway.
we get:

float B = dot(eyepos, ray);
float Bsq = B * B;
float Cpart = dot(eyepos, eyepos);
float C = Cpart - innerRadius*innerRadius;
float discr = Bsq - C;
bool bVisible = discr < 0 || -B - std::sqrt(discr) <= 0) && -B + std::sqrt(discr) <= 0;

Now you might look at the bVisible boolean expression and wonder if it also can't be simplified any further, and yes indeed it is possible. In particular, the factors between the && signs:
We start by letting D = sqrt(discr) and multiplying both expressions by -1 and we get:

D + B >= 0 && -D + B >= 0

suppose the case that the left hand side is false, e.g D + B <= 0, if we subtract 2D from both sides of this equation we get

-D + B <= -2D <= 0

,which means the right hand side will also be false.
since -D + B < D + B, when the right hand side IS true, the lhs will also be true.

this allows us to write the expression as :
 bVisible = discr < 0 || B >= std::sqrt(discr); 



Hope you enjoyed reading it and learned something

*****
I don't particularly like you.
-Kaiser-
Profile Blog Joined November 2011
Canada932 Posts
March 08 2014 07:28 GMT
#2
I think you're smarter than me.
3 Hatch Before Cool
TheEmulator
Profile Blog Joined July 2010
28098 Posts
March 08 2014 08:17 GMT
#3
On March 08 2014 16:28 -Kaiser- wrote:
I think you're smarter than me.

Makes two of us
Administrator
Biolunar
Profile Joined February 2012
Germany224 Posts
Last Edited: 2014-03-08 08:37:59
March 08 2014 08:37 GMT
#4
On March 08 2014 10:35 fmod wrote:
float fCos = 1 - (nAngle + nAngle) / (float)mHeight;


Make that a
static_cast<float>(mHeight)
and I am happy

Btw replacing any sine/cosine functions from the standard library is always a good idea. I’ve read that they are pretty buggy if the argument gets too high, but I haven’t checked myself.
What is best? To crush the Zerg, see them driven before you, and hear the lamentations of the Protoss.
Clazziquai10
Profile Blog Joined August 2011
Singapore1949 Posts
March 08 2014 13:07 GMT
#5
I'm a computer science major and I have no idea what's going on here *hangs head in shame*
Mr. Wiggles
Profile Blog Joined August 2010
Canada5894 Posts
March 08 2014 18:13 GMT
#6
I'd be interested in seeing how much of a difference this makes in terms of performance in addition to cleaning up the code. You save yourself several calculations here by making the code simpler.

Did you profile the code at all to compare its performance before and after improving it? It would be cool to see that by applying some more math to the problem, you're not only able to improve the code readability and clarity, but also the performance.
you gotta dance
Hryul
Profile Blog Joined March 2011
Austria2609 Posts
Last Edited: 2014-03-08 19:20:58
March 08 2014 19:17 GMT
#7
the thing that interested me most was how you managed to impelement TeX code here. Then I found out it was a pasted pic
Edit: not that the other stuff is uninteresting. math is a useful skill toi have.
Countdown to victory: 1 200!
Cyx.
Profile Joined November 2010
Canada806 Posts
March 08 2014 19:38 GMT
#8
Since you already have Bsq you could save yourself one more call to std::sqrt() by writing the last expression as

bVisible = discr < 0 || Bsq >= discr;

BirdKiller
Profile Joined January 2011
United States428 Posts
Last Edited: 2014-03-08 22:19:56
March 08 2014 22:16 GMT
#9
On March 09 2014 03:13 Mr. Wiggles wrote:
I'd be interested in seeing how much of a difference this makes in terms of performance in addition to cleaning up the code. You save yourself several calculations here by making the code simpler.

Did you profile the code at all to compare its performance before and after improving it? It would be cool to see that by applying some more math to the problem, you're not only able to improve the code readability and clarity, but also the performance.


We can estimate the theoretical relative performance decrease/increase by looking into the computational complexity of each of the operations and functions. For example, suppose the functions and operations like addition, sin, square root, etc., follow the complexity linked here:

http://en.wikipedia.org/wiki/Computational_complexity_of_mathematical_operations

In the original code, the first block that we looked into called 3 functions/operations: arccos, sin, cos. This has a combined time complexity of 3 * O(log(n)^2 * M(n)). In complexity arithmetic, we don't care about constants so the block has a complexity of O(log(n)^2 * M(n)). Don't worry about what M(n) is; we're just comparing, not computing.

In the modified code, the first block now calls several functions/operations with equivalent complexity: subtraction x2, addition, division, and square root. This has a combined time complexity of O(M(n)).

Not even knowing which multiplication algorithm the program/compiler is using, we can then argue that the modified code is faster by a factor of log(n)^2. This is quite small I would say. However, this is under A LOT of assumptions, chiefly that the compiler is so dumb such that it couldn't figure this optimization out on its own and that the algorithms used for trigonometric functions is equivalent to that used by the program/compiler.
fmod
Profile Blog Joined November 2013
Cayman Islands330 Posts
March 08 2014 23:06 GMT
#10
On March 09 2014 04:38 Cyx. wrote:
Since you already have Bsq you could save yourself one more call to std::sqrt() by writing the last expression as

bVisible = discr < 0 || Bsq >= discr;


That'll only work for positive B though. The square root is assumed to be positive always. If not the early out behaviour of || will assure it never gets there,

BirdKiller you are right that these are very 'micro' optimizations. I mostly posted this because it interested me and maybe others as well. One thing though is that by avoiding (inverse) trig functions the result will usually be more accurate, apart from being faster.
I don't particularly like you.
Please log in or register to reply.
Live Events Refresh
Next event in 6h 57m
[ Submit Event ]
Live Streams
Refresh
StarCraft 2
MindelVK 23
elazer 18
StarCraft: Brood War
Sea 30547
Britney 29494
Shuttle 1756
Mini 441
actioN 388
Soma 381
Soulkey 349
firebathero 334
Rush 186
Dewaltoss 144
[ Show more ]
Mong 106
PianO 48
Backho 43
sSak 25
Rock 17
Terrorterran 16
soO 11
Dota 2
qojqva3700
Counter-Strike
fl0m3670
pashabiceps1634
adren_tv29
Other Games
tarik_tv7332
Grubby2956
singsing2117
FrodaN1513
B2W.Neo609
Beastyqt468
QueenE111
Hui .85
C9.Mang068
Trikslyr55
Mew2King43
Organizations
Other Games
BasetradeTV187
Counter-Strike
PGL81
StarCraft 2
angryscii 26
Blizzard YouTube
StarCraft: Brood War
BSLTrovo
sctven
[ Show 16 non-featured ]
StarCraft 2
• poizon28 108
• Shameless 40
• Reevou 2
• AfreecaTV YouTube
• intothetv
• Kozan
• IndyKCrew
• LaughNgamezSOOP
• Migwel
• sooper7s
StarCraft: Brood War
• BSLYoutube
• STPLYoutube
• ZZZeroYoutube
League of Legends
• TFBlade1289
• Shiphtur367
Other Games
• WagamamaTV1
Upcoming Events
PiGosaur Cup
6h 57m
Replay Cast
14h 57m
Replay Cast
1d 5h
The PondCast
1d 15h
KCM Race Survival
1d 15h
WardiTV Winter Champion…
1d 17h
Replay Cast
2 days
Ultimate Battle
2 days
Light vs ZerO
WardiTV Winter Champion…
2 days
Classic vs Nicoract
herO vs YoungYakov
ByuN vs Gerald
Clem vs Krystianer
Replay Cast
3 days
[ Show More ]
CranKy Ducklings
3 days
WardiTV Winter Champion…
3 days
MaxPax vs Spirit
Bunny vs Rogue
Cure vs SHIN
Solar vs Zoun
Replay Cast
4 days
Sparkling Tuna Cup
4 days
WardiTV Winter Champion…
4 days
Replay Cast
5 days
Replay Cast
5 days
Monday Night Weeklies
5 days
Replay Cast
6 days
Liquipedia Results

Completed

Proleague 2026-03-02
PiG Sty Festival 7.0
Underdog Cup #3

Ongoing

KCM Race Survival 2026 Season 1
Jeongseon Sooper Cup
Spring Cup 2026
WardiTV Winter 2026
Nations Cup 2026
ESL Pro League S23 Stage 1&2
PGL Cluj-Napoca 2026
IEM Kraków 2026
BLAST Bounty Winter 2026
BLAST Bounty Winter Qual
eXTREMESLAND 2025

Upcoming

ASL Season 21: Qualifier #1
ASL Season 21: Qualifier #2
ASL Season 21
Acropolis #4 - TS6
Acropolis #4
IPSL Spring 2026
CSLAN 4
HSC XXIX
uThermal 2v2 2026 Main Event
Bellum Gens Elite Stara Zagora 2026
RSL Revival: Season 4
NationLESS Cup
Asian Champions League 2026
IEM Atlanta 2026
PGL Astana 2026
BLAST Rivals Spring 2026
CCT Season 3 Global Finals
IEM Rio 2026
PGL Bucharest 2026
Stake Ranked Episode 1
BLAST Open Spring 2026
ESL Pro League S23 Finals
TLPD

1. ByuN
2. TY
3. Dark
4. Solar
5. Stats
6. Nerchio
7. sOs
8. soO
9. INnoVation
10. Elazer
1. Rain
2. Flash
3. EffOrt
4. Last
5. Bisu
6. Soulkey
7. Mini
8. Sharp
Sidebar Settings...

Advertising | Privacy Policy | Terms Of Use | Contact Us

Original banner artwork: Jim Warren
The contents of this webpage are copyright © 2026 TLnet. All Rights Reserved.