Schroedingers-Hat / jsphys

Libraries for physics simulation on javascript canvas
GNU Affero General Public License v3.0
11 stars 1 forks source link

Doppler shifting of any color #14

Open capnrefsmmat opened 13 years ago

capnrefsmmat commented 13 years ago

We'll need to eventually handle Doppler shifting an arbitrary color. We need:

The colors can be thrown into dopplerShiftColor the same way color temperatures are.

Schroedingers-Hat commented 13 years ago

RGB to wavelength is not overly meaningful (useful for pretties, but somewhat misleading). Far Red+Violet and green act differently. I don't know how differently, so this will be an educational experience as well :D

My thought was to implement our own n channel colors, something like

VHF UHF, Microwave, far IR, near IR, R, O, Y, G, B, I, V, UVA, UVB, X-Rays, Gamma rays.

But spaced logarithmically

Then have a vector of sensitivities vs wavelength of the human eye for each channel R, G, B (could include rods and a scaling factor, too. This will allow a much greater range of luminosities to be viewed and allow simulating night vision into the package. It will also allow implementing the headlight effect by multiplying by a number (I think it's our doppler shift value, will have to think), rather than writing a whole separate method.) For each channel in our generalized color, find the doppler shifted wavelength, and multiply by the appropriate value. (a fast method may be index by the log of the frequency/wavelength)

A number of common materials can then be indexed. This will give an accurate, if somewhat imprecise representation of what things look like red/blue shifted. (think matching screen colors to real colors in the 256 color days). It should also be reasonably fast, although large numbers of objects are ill advised. Good thing stars are black bodies ^_^

Schroedingers-Hat commented 13 years ago

Going as far as microwaves will allow CMBR to become visible at sufficient speed. Other fun radio wave emitters include Jupiter and distant galaxies.

capnrefsmmat commented 13 years ago

Some educational links for my future reference:

http://paulbourke.net/texture_colour/convert/ has a "Frequency to RGB" section which claims it is an "involved procedure" which should be computed in advance, rather than on the fly, though it was written in 1994 and I don't know if computing power has made that unnecessary now.

http://www.fourmilab.ch/documents/specrend/ can turn an arbitrary spectrum into RGB values. It may be more useful. It supplies a blackbody spectrum function, but we could create our own spectra, including gamma functions which just have one frequency.

Schroedingers-Hat commented 13 years ago

The second one looks like just the thing I was hoping for. We doppler shift our spectral data and feed the values which lie in the visible spectrum into it.

Schroedingers-Hat commented 13 years ago

Not that I fully understand what he's doing, but only significant change in the algorithm I can see that we'll need is this line: for (i = 0, lambda = 380; lambda < 780.1; i++, lambda += 5) { should just iterate through the known lambda values instead of every 5 nanometers. even looks like handling arbitrary length spectrum arrays will be as/more simple.

A fallback to the black body code might be a good idea if objectTemp*dopplerfactor is more than about 3000 Kelvin, that way we don't have to record as much in the spectrum.

Not sure how much of this is blatantly obvious. Do tell me if I'm being condescending.

capnrefsmmat commented 13 years ago

What do you mean by "the known lambda values"? Which lambdas do we know?

I was planning on replacing the current blackbody code with the Fourmilab code, since it can calculate the RGB for any arbitrary blackbody radiator. We could keep the current table, or something similar, for speed in the known range, if you'd like.

(Or I can use the Fourmilab code, with slight modifications, to just generate a much larger data table.)

Schroedingers-Hat commented 13 years ago

Well, I was thinking for using arbitrary spectra. Look up the spectrum for, say, CO2 illuminated by sunlight (or calculate it from spectroscopy data multiplied by a black body spectrum). Divide it into bins, automatically or by hand. 'It's this bright over the range 700-800nm' etc. Then record a vector Wavelength 750nm 500nm...etc Intensity 0.4 0.1 ...etc scale the wavelength by the doppler factor and then feed the values which lie in the visible spectrum into specrend

capnrefsmmat commented 13 years ago

Ah. You can provide a spectrum function, so we could write a function which simply returns the brightness of the nearest defined wavelength, then pass that into the premade rendering function. It'll try to get more detail than the spectrum has, but it'll allow us to use any arbitrary spectrum we want.

Sounds good otherwise. I'm working on porting the code to JavaScript so I can use it for blackbodies right now, but we'll be able to substitute in any spectrum we want later.

Schroedingers-Hat commented 13 years ago

For bonus points we can also multiply the intensity values by doppler factor, then make the normalization factor (yw I think) available. This way we automatically simulate using the appropriate sensitivity of camera/iris opening closing and make code available if we ever want to implement bloom from very bright sources.

Schroedingers-Hat commented 13 years ago

May be worthwhile keeping the lookup table version around. I was thinking of creating a scenery class which has no velocity or position, only angle, luminosity and temp. This can be used for distant galaxies, cosmic microwave background radiation, or to just pretty things up a bit.

Also forgot to mention that the purpose of the intensity multiplication thing is to simulate the headlight effect.

capnrefsmmat commented 13 years ago

So have we decided that, since we can do shadows around oversaturated objects, we can implement arbitrary Doppler shifting and do the headlight effect with the Y coordinate in CIE XYZ?

Schroedingers-Hat commented 13 years ago

Yeah, it'll take a bit of tweaking and playing with parameters, but shouldn't be too bad.

capnrefsmmat commented 13 years ago

I was thinking something like this: For object colors, truncate RGB values like we do currently. For the shadows, scale the RGB values down so the highest value is 1 and the others are scaled down proportionately. The shadow size can be proportional to how much higher than 1 the highest value is, so it reflects the amount of glare.

Schroedingers-Hat commented 13 years ago

hmm, there's another normalization step in there somewhere which is what is making everything the same luminosity. I recall I got rid of it when playing around in dopplerheadlight.

If it's at all possible, I'd like to separate the color (hue and saturation) from the lum, and perhaps even get lum in watts/m^2 or watts/solid arcsecond, because right now we don't really have any way of getting testable data to see if what's happening is vaguely accurate.

this is sounding rather complicated :/ Perhaps it'd be best do what you suggest, and we can try to get something accurate later.

capnrefsmmat commented 13 years ago

Yeah, I don't know how to represent luminosity in watts/m^2 given a CIE XYZ Y coordinate. I'll try my strategy and see how it works.

capnrefsmmat commented 13 years ago

Status update, since I said we should do this:

The doppler branch has a simple, untested Gaussian function in e430ce82b. When I get back to this, I'll test it, then I need to construct some wrapper functions that'll cache the Doppler-shifted values and such. Then try to draw with it.

capnrefsmmat commented 13 years ago

I think I'll punt this to a future version for now. Everything can stay a black body for the initial demos.

Schroedingers-Hat commented 12 years ago

I thought of a good way to do this type of thing. xyz/Y are linear so: We could create a function/bunch of functions, for base spectrum -- say one for each ROYGBIV, a few temperatures of black body, few gaussians in IR/radio/UV Then calculate a cache for each of these for different doppler values (say 30 each) of xyz or xyzY vectors, call it M. Then an object can have different spectra with different intensities I all we have to do is find the vector M1_I1 + M2_I2 .... then do our normalization and convert to RGB step. Finally Y can be used for Lum. Side-benefit: Gives easy handling for headlight effect. Also we'd have to fix up black body to do a change of variable rather than multiplying the temperature.

Schroedingers-Hat commented 12 years ago

Individual wavelengths are slightly off their true colour. I would suspect the modifications I made to unlock the brightness, although I cannot think of how they would modify the hue. @capnrefsmmat Other suspects include an off by one error in your arrays, are you able to check this out? Although it's a touch more than 5nm. Edit: Odd, ramping up the brightness even further appears to fix it somewhat. I think it may be attributable to the non-linearity of RGB along with the rather extreme levels of Gamma I used to fit in the dynamic range we're seeing.

capnrefsmmat commented 12 years ago

Also worth noting that "true color" is a misnomer, since the conversion to RGB is based on estimates of the sensitivity of the different color receptors in the eye. Anyone who uses different estimates will give a different RGB value for a given wavelength.

capnrefsmmat commented 12 years ago

Heh. Doppler-shifting photons causes a few problems -- Greedo's laser pulse in the second step of the Han and Greedo demo is invisible, since it's redshifted too far. We'll have to tweak wavelengths to keep it visible.

Schroedingers-Hat commented 12 years ago

or make it a toggle-able setting? I don't think it's appropriate all the time anyway re. true colour, most people point to roughly the same place in the rainbow when you ask which bit is yellow/orange. Before I fiddled with the brightness those wavelengths more orange/red (ie. error was more than variance)

capnrefsmmat commented 12 years ago

or make it a toggle-able setting? I don't think it's appropriate all the time anyway

Definitely. It looks like this'll be a common problem, because several demos suffer from it. Han and Greedo just goes at 0.3c, so it doesn't take high velocities to cause it.

We might use the existing showDoppler switch for this. Seems easy enough.

Schroedingers-Hat commented 12 years ago

You can get a little wiggle room by using green rather than red. Or at least a green-er red. There's not much visible spectrum past 680nm

Schroedingers-Hat commented 12 years ago

-_- Just realised all we have to do for monochromatic light is multiply by the relevant value of CIE_COLOR_MATCH and we're done (for XYZ space at least).