What is the minimum distance between two colors to be easily distinguishable? - user-experience

I need to draw a Sierpinski Triangle for some homework.
The task includes a random color picker for the triangle. As the background is white this may lead to problems with visibility.
My question is what is the minimum distance between two rgb values for them to still be easily distinguishable?
I am aware that this is rather subjective and depends on monitor, ambient light and the definition of "easily distinguishable" but a rough estimate would suffice. Web searches were mostly concerned with physical distance.

Related

What units should I use for lighting in a 3D rendering engine?

In reading academic papers on rendering, graphics processing, lighting, etc..., I am finding a wide variety of units mentioned and used.
For example, Bruneton's Atmospheric Scattering paper seems to use candellas per square meter (cd/m^2), representing luminance. However, Jensen's Night Model uses watts per square meter (W/m^2), implying irradiance. Other papers mention irradiance, luminance, illuminance, etc., with seemingly no common representation of the lighting calculations used. How then, can one even be sure that in implementing all of these papers, that the calculations will "play well" together?
To add to the confusion, most papers on adaptive tonemapping seem to forego units at all, merely recommending that pixels (referred to as luminance) be rendered in a log format (decibels). A decibel is useless without a reference intensity/power.
Which begs the question, what unit does a single pixel represent? When I calculate the "average luminance" of a scene by averaging the log-brightness of the pixels, what exactly am I calculating? The term "luminance" itself implies an area being illuminated and a solid angle for the source. This leads to two more questions: "What is the solid angle of the point source?" "What is the area of a pixel?"
My question is thus,
What units should lighting in a 3d graphics engine be represented in to allow for proper, calibrated brightness control across a wide variety of light sources, from faint starlight to bright sunlight, and how does this unit relate to the brightness of individual pixels?
Briefly: radiance, measured in candela per square meter (cd/m^2) is the appropriate unit.
Less briefly: computer graphics is usually concerned with what things should look like to people. The units that describe this are:
"luminous flux" is measured in lumens, or lm, which are defined proportional to the total radiated power (in watts) of light at a particular wavelength.
"luminous intensity" is measured in candela, or cd, which can be defined as lumens per steradian (lm/sr).
Intuitively, when you spread the same amount of energy over a larger area, it becomes proportionately less bright. This yields two more quantities:
"irradiance" is the luminous flux per unit area. It is measured in lm/m^2, and is proportional to W/m^2.
"radiance" is the luminous intensity per unit area. It is measured in cd/m^2, or lm/(sr.m^2).
Now, to answer your questions:
Each pixel represents a finite amount of solid angle from the camera, which is measured in steradian. In the context of your question, the relevant area is the area of the object being rendered.
The radiance (measured in cd/m^2) represents surface brightness, and has the unique property that it is invariant along any unobstructed path of observation (which makes it the most appropriate quantity for a rendering engine). The color of each pixel represents the average radiance over the solid angle occupied by that pixel.
Note that, by definition, a point source doesn't occupy any solid angle; its radiance is technically infinite. Its irradiance is finite, though, and technically it should only contribute a finite (if potentially large) effect to a given pixel value. In any case, if you want to directly render point sources, you will need to treat them differently from area sources, and deal with the problem that quantities other than radiance are not invariant over a given ray...
When Jensen et al's paper "A Physically-Based Night Sky Model" uses an irradiance-related W/m^2 in a table of various sources of illumination, I would guess that their intention was to describe their relative contribution as averaged over the entire night sky, as abstracted from any visual details.
Finally, note that truly physically based models need to integrate over the observable spectrum in order to evaluate brightness and color. Thus, such models must start out with a distribution of watts over visible wavelengths, and use the standard human colorimetric model to evaluate lumens.
The SI unit for brightness is the Candela per square metre so if your wanting to represent actual physical quantities it would be hard to argue against using that. As for how this unit relates to the brightness of an individual pixel that would be a function of the brightness at that part of the illumination source represented in the pixels viewing area combined with contributions from elsewhere in the scene as calculated by the engine - presumably this would very completely depending on the renderer.

CIE-L*u*v* color interpolation

I'm writing a vertex decimator that needs to interpolate vertex colors on a mesh. I'm reading Level of Detail for 3D Graphics for domain material. In the color interpolation secion, the book goes on to suggest using the CIE-Luv* color space to perform perceptual linear interpolation of colors.
The translation equations to and from the CIE XYZ color space are provided. I am able to implement the equations it provides, but Wikipedia leaves out numeric values of the following variables: u'n, v'n, and Yn.
The article say these values depend on a "specified white point" and its "luminance". It suggests u'n = 0.2009 and v'n = 0.4610 when using 2° observer and standard illuminant C. If I am using these, what would Yn be? I do not know enough physics to figure this out, and I have been unable to search for an answer on Google.
In the end, my question boils down to: What are satisfactory/appropriate values I can use for u'n, v'n, and Yn?
Also, I'm assuming I simply linearly interpolate piecewise each component of CIE-Luv* (L*, u*, and v*) when interpolating values in this color space. Is this correct?
These three values are left out its because they depend on the colorspace of the specific device (e.g. display, printer or camera). Since computer screens use an RGB colorspace where perceived grey are R=B=G, you can assume that the values are not device dependant. I can't remember the values of by heart, so I'll edit them in later.
The human eye perceives luminance/intensity logarithmically, however, a linear interpolation is close enough, especially since you don't know what the actual min and max screen levels are.
The human eye perceives the color angle linearly, however, you need to take into account that the angle id's cyclic, therefore, the interpolation of the min and max angles should equal min (or max) and not the half way point. E.g. average of purple and red should be purple.
I think that the perception of saturation is also logarithmic, however, can be approximated by a linear interpolation.
Edit:
It seems like most sites use the sRGB to XYZ formulas.
http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
http://www.easyrgb.com/index.php?X=MATH&H=02#text2
http://colormine.org/convert/rgb-to-xyz

How to structure Point Light Sources?

I am using Java to write a very primitive 3D graphics engine based on The Black Art of 3D Game Programming from 1995. I have gotten to the point where I can draw single color polygons to the screen and move the camera around the "scene". I even have a Z buffer that handles translucent objects properly by sorting those pixels by Z, as long as I don't show too many translucent pixels at once. I am at the point where I want to add lighting. I want to keep it simple, and ambient light seems simple enough, directional light should be fairly simple too. But I really want point lighting with the ability to move the light source around and cast very primitive shadows ( mostly I don't want light shining through walls ).
My problem is that I don't know the best way to approach this. I imagine a point light source casting rays at regular angles, and if these rays intersect a polygon it will light that polygon and stop moving forward. However when I think about a scene with multiple light sources and multiple polygons with all those rays I imagine it will get very slow. I also don't know how to handle a case where a polygon is far enough away from a light source that if falls in between two rays. I would give each light source a maximum distance, and if I gave it enough rays, then there should be no point within that distance that any two rays are too far apart to miss a polygon, but that only increases my problem with the number of calculations to perform.
My question to you is: Is there some trick to point light sources to speed them up or just to organize it better? I'm afraid I'll just get a nightmare of nested for loops. I can't use openGL or Direct3D or any other cheats because I want to write my own.
If you want to see my results so far, here is a youtube video. I have already fixed the bad camera rotation. http://www.youtube.com/watch?v=_XYj113Le58&feature=plcp
Lighting for real time 3d applications is (or rather - has in the past generally been) done by very simple approximations - see http://en.wikipedia.org/wiki/Shading. Shadows are expensive - and have generally in rasterizing 3d engines been accomplished via shadow maps & Shadow Volumes. Point lights make shadows even more expensive.
Dynamic real time light sources have only recently become a common feature in games - simply because they place such a heavy burden on the rendering system. And these games leverage dedicated graphics cards. So I think you may struggle to get good performance out of your engine if you decide to include dynamic - shadow casting - point lights.
Today it is commonplace for lighting to be applied in two ways:
Traditionally this has been "forward rendering". In this method, for every vertex (if you are doing the lighting per vertex) or fragment (if you are doing it per-pixel) you would calculate the contribution of each light source.
More recently, "deferred" lighting has become popular, wherein the geometry and extra data like normals & colour info are all rendered to intermediate buffers - which is then used to calculate lighting contributions. This way, the lighting calculations are not dependent on the geometry count. It does however, have a lot of other overhead.
There are a lot of options. Implementing anything much more complex than some the basic models that have been used by dedicated graphics cards over the past couple of years is going to be challenging, however!
My suggestion would be to start out with something simple - basic lighting without shadows. From there you can extend and optimize.
What are you doing the ray-triangle intersection test for? Are you trying to light only triangles which the light would reach? Ray-triangle
intersections for every light with every poly is going to be very expensive I think. For lighting without shadows, typically you would
just iterate through every face (or if you are doing it per vertex, through every vertex) and calculate & add the lighting contribution per light - you would do this just before you start rasterizing as you have to pass through all polys in anycase.
You can calculate the lighting by making use of any illumination model, something very simple like Lambertian reflectance - which shades the surface based upon the dot product of the normal of the surface and the direction vector from the surface to the light. Make sure your vectors are in the same spaces! This is possibly why you are getting the strange results that you are. If your surface normal is in world space, be sure to calculate the world space light vector. There are a bunch of advantages for calulating lighting in certain spaces, you can have a look at that later on, for now I suggest you just get the basics up and running. Also have a look at Blinn-phong - this is the shading model graphics cards used for many years.
For lighting with shadows - look into the links I posted. They were developed because realistic lighting is so expensive to calculate.
By the way, LaMothe had a follow up book called Tricks of the 3D Game Programming Gurus-Advanced 3D Graphics and Rasterization.
This takes you through every step of programming a 3d engine. I am not sure what the black art book covers.

SVG plot from point-value pairs

I need to write some code (for a web.py webapp with a straight-HTML/JS client) that will generate a visual representation of a set of point-values. Each point has an X and Y coordinate, and the value is an integer. If I can use SVG to do this, then I can scale the image client-side with no extra code. Can I actually do this? I am concerned about a couple of things:
The points don't necessarily have any relation to each other. They aren't necessarily in a grid, nor can we say how many points are nearby, etc.
Gradients are primarily one-direction, and multiple gradients on the same shape seems to be a foreign concept.
Fills require an existing image, at which point, I'd be better off generating the entire image server-side anyway.
Objects always have a layering, even if it isn't specified, which can change how the image is rendered.
If it helps, consider a situation where we have a point surrounded by 5 others, where one of them is a bit closer than the others (exact distances and sizes can be adjusted). All six of the points have different colors (Red, Green, Blue, Cyan, Magenta, Yellow, with red in the center and Yellow being slightly closer), and the outer five points are arranged roughly in a pentagon. Note that this situation is not the only option, just a theoretically possible situation.
Can I do this with SVG, or should I render an image server-side?
EDIT: The main difficulty isn't in drawing the points, it is in filling the space between the points so that there is no whitespace, and color transitions aren't harsh/unpredictable if you know the data.
I don't entirely understand the different issues you are having with wanting to use svg. I am currently using the set up you are describing to render X-Y scatter plots and gaussian curves and found that it works great.
Regarding the last point about object layering, you have to be particularly careful when layering objects with less than 100% opacity which are different colors. The way the colors "add" depends on the order in which you add the objects to your svg drawing.
Thankfully you can use different filters to overlay the colors without blending them. Specifically I am using the FeComposite filter element. There is a good example of its usage here:
http://www.w3.org/TR/SVG/filters.html#feCompositeElement

circle drawing algorithm for n-pixel border

I know the Bresenham and related algorithms, and I found a good algorithm to draw a circle with a 1-pixel wide border. Is there any 'standard' algorithm to draw a circle with an n-pixel wide border, without restoring to drawing n circles?
Drawing the pixel and n2 surrounding pixels might be a solution, but it draws many more pixels than needed.
I am writing a graphics library for an embedded system, so I am not looking for a way to do this using an existing library, although a library that does this function and is open source might be a lead.
Compute the points for a single octant for both radii at the same time and simultaneously replicate it eight ways, which is how Bresenham circles are usually drawn anyway. To avoid overdrawing (e.g., for XOR drawing), the second octant should be constrained to draw outside the first octant's x-extents.
Note that this approach breaks down if the line is very thick compared to the radius.
Treat it as a rasterization problem:
Take the bounding box of your annulus.
Consider the image rows falling in the bounding box.
For each row, compute the intersection with the 2 circles (ie solve x^2+y^2=r^2, so x=sqrt(r^2-y^2) for each, for x,y relative to the circle centres.
Fill in the spans. Repeat for next row.
This approach generalizes to all sorts of shapes, can produce sub-pixel coordinates useful for anti-aliasing and scales better with increasing resolution than hacky solutions involving multiple shifted draws.
If the sqrt looks scary for an embedded system, bear in mind there are fast approximate algorithms which would probably be good enough, especially if you're rounding off to the nearest pixel.

Resources