<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>Darking pixels...</title>
		<link>http://www.allegro.cc/forums/view/554333</link>
		<description>Allegro.cc Forum Thread</description>
		<webMaster>matthew@allegro.cc (Matthew Leverton)</webMaster>
		<lastBuildDate>Wed, 21 Dec 2005 22:24:28 +0000</lastBuildDate>
	</channel>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I&#39;m using a Mode7 technique and have decided that I&#39;d like to darken pixels that appear far away from the camera. I was just wondering how to do this? I first use getpixel to grab the pixel colour. So I need some code to go between getpixel and putpixel that will darken the pixel dependant upon distance!
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (ngiacomelli)</author>
		<pubDate>Tue, 20 Dec 2005 23:24:50 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>To darken the pixel, you might try:</p><div class="source-code snippet"><div class="inner"><pre><span class="k1">int</span> c <span class="k3">=</span> original_value<span class="k2">;</span>
<span class="k1">float</span> h, s, v<span class="k2">;</span>
<span class="c">// Convert to HSV color coordinates</span>
<a href="http://www.allegro.cc/manual/rgb_to_hsv" target="_blank"><span class="a">rgb_to_hsv</span></a><span class="k2">(</span><a href="http://www.allegro.cc/manual/getr" target="_blank"><span class="a">getr</span></a><span class="k2">(</span>c<span class="k2">)</span>, <a href="http://www.allegro.cc/manual/getg" target="_blank"><span class="a">getg</span></a><span class="k2">(</span>c<span class="k2">)</span>, <a href="http://www.allegro.cc/manual/getb" target="_blank"><span class="a">getb</span></a><span class="k2">(</span>c<span class="k2">)</span>, <span class="k3">&amp;</span>h, <span class="k3">&amp;</span>s, <span class="k3">&amp;</span>v<span class="k2">)</span><span class="k2">;</span>
<span class="c">// Distance is 0 at the bottom of the screen, 1 at the horizon</span>
<span class="k1">float</span> distance <span class="k3">=</span> <span class="k2">(</span><span class="k1">float</span><span class="k2">)</span> <span class="k2">(</span><a href="http://www.allegro.cc/manual/SCREEN_H" target="_blank"><span class="a">SCREEN_H</span></a> <span class="k3">-</span> my_y<span class="k2">)</span> <span class="k3">/</span> <span class="k2">(</span><a href="http://www.allegro.cc/manual/SCREEN_H" target="_blank"><span class="a">SCREEN_H</span></a> <span class="k3">-</span> horizon_y<span class="k2">)</span><span class="k2">;</span>
<span class="c">// Scale the value (distance from black) down proportional to the distance</span>
v <span class="k3">*</span><span class="k3">=</span> <span class="n">1</span> <span class="k3">-</span> distance<span class="k2">;</span>
<span class="c">// Convert back to RGB coordinates</span>
<span class="k1">int</span> r, g, b<span class="k2">;</span>
<a href="http://www.allegro.cc/manual/hsv_to_rgb" target="_blank"><span class="a">hsv_to_rgb</span></a><span class="k2">(</span>h, s, v, <span class="k3">&amp;</span>r, <span class="k3">&amp;</span>g, <span class="k3">&amp;</span>b<span class="k2">)</span><span class="k2">;</span>
<span class="k1">int</span> new_color <span class="k3">=</span> makcol<span class="k2">(</span>r, g, b<span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>Now, this method will product pretty results where horizon pixels are black and close pixels are full color. You can make it so horizon pixels are brighter by scaling distance. Try <tt>distance *= .7</tt> before we scale the value <tt>v</tt>.</p><p>Of course, this method is slow. If it&#39;s too slow, you can just multiply <tt>r</tt>, <tt>g</tt>, and <tt>b</tt> by distance to accomplish a (I believe) similar effect.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (CGamesPlay)</author>
		<pubDate>Tue, 20 Dec 2005 23:35:33 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Obviously I need to first suggest that for speed reasons you don&#39;t use getpixel or putpixel anywhere that you are doing significant graphics work but instead check out the &quot;Direct access to video memory&quot; section of the manual and apply various methods there. Don&#39;t worry - they all work on memory bitmaps too.</p><p>However to directly answer your question - Allegro will help you through its support for conversions between HSV and RGB colour spaces.</p><p>Get the r, g and b components for the pixel you want to darken. Use Allegro function rgb_to_hsv to get h, s and v components for your colour. The v component is &quot;brightness&quot; and in the Allegro world is a floating point number ranging from 0 to 1. Multiply it by an amount chosen to reflect the darkening you want to perform on the line. Then put the h, s and v into hsv_to_rgb and use the result to plot your new pixel.</p><p>As for deciding how far to darken based on depth, many people use &quot;linear fog&quot;. That means that the brightness at z = n is twice that at z = 2n. So, you could divide your v by z.</p><p>EDIT: just beaten on the HSV front, I see! Incidentally, if you have a fixed camera height and rotation towards the ground you can just create a single bitmap that contains darkened scanlines and blit that transparently after normal floor drawing. In a roundabout fashion this is what SNES games do.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Thomas Harte)</author>
		<pubDate>Tue, 20 Dec 2005 23:35:40 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>The HSV stuff can be precalculated, and stored in a table.<br />After working out the distance, you transform it into an integer range<br />(say, 0-255) and you lookup each of R, G and B into it, then you<br />reform the triplet.<br />You ought to have one version of this per color depth, to avoid the<br />constant tests against the color depth in the inner loop.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (vpenquerch)</author>
		<pubDate>Tue, 20 Dec 2005 23:54:15 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Some fantastic reponses! Thank you all. </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Obviously I need to first suggest that for speed reasons you don&#39;t use getpixel or putpixel anywhere that you are doing significant graphics work but instead check out the &quot;Direct access to video memory&quot; section of the manual and apply various methods there. Don&#39;t worry - they all work on memory bitmaps too.
</p></div></div><p>

Well, I&#39;ve never tried anything like that before. I found some nice code for a faster putpixel in the manual. I wrote a new getpixel using the putpixel example. It seems to work correctly. But if I&#39;ve done something terribly wrong... please tell me <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" /></p><div class="source-code snippet"><div class="inner"><pre><span class="k1">void</span> fast_putpixel<span class="k2">(</span><a href="http://www.allegro.cc/manual/BITMAP" target="_blank"><span class="a">BITMAP</span></a> <span class="k3">*</span>bmp, <span class="k1">int</span> x, <span class="k1">int</span> y, <span class="k1">int</span> color<span class="k2">)</span>
<span class="k2">{</span>
      <span class="k2">(</span><span class="k2">(</span><span class="k1">long</span> <span class="k3">*</span><span class="k2">)</span>bmp-&gt;line<span class="k2">[</span>y<span class="k2">]</span><span class="k2">)</span><span class="k2">[</span>x<span class="k2">]</span> <span class="k3">=</span> color<span class="k2">;</span>
<span class="k2">}</span>

<span class="k1">int</span> fast_getpixel<span class="k2">(</span><a href="http://www.allegro.cc/manual/BITMAP" target="_blank"><span class="a">BITMAP</span></a> <span class="k3">*</span>bmp, <span class="k1">int</span> x, <span class="k1">int</span> y<span class="k2">)</span>
<span class="k2">{</span>
      <span class="k1">return</span> <span class="k2">(</span><span class="k2">(</span><span class="k1">long</span> <span class="k3">*</span><span class="k2">)</span>bmp-&gt;line<span class="k2">[</span>y<span class="k2">]</span><span class="k2">)</span><span class="k2">[</span>x<span class="k2">]</span><span class="k2">;</span>
<span class="k2">}</span>
</pre></div></div><p>

I wont give cookies until I&#39;ve tried the distance shading out! <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (ngiacomelli)</author>
		<pubDate>Wed, 21 Dec 2005 00:17:46 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>If you try to acces a pixel outside of the bitmap with those functions the world <i>might</i> explode. Please be careful (for all our sakes).
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Jonny Cook)</author>
		<pubDate>Wed, 21 Dec 2005 05:09:55 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>And if you need RIDICULOUSLY FAST code, you can use subtraction instead of multiplication (it&#39;s not correct, but looks OK and it&#39;s a lot faster), and pre-calculate the values into a 1-dimensional table based on scanline.<br />Or if you have a few cpu cycles to spare, you can interpolate between the texel color and a fog color instead of black (again, you can use a scanline-based precalc table). This way, you can easily create different moods for different scenes (IIRC, F-Zero did this).
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Tobias Dammers)</author>
		<pubDate>Wed, 21 Dec 2005 05:12:57 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Everything worked fine <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" /> Except... I just noticed that the title for this thread should be: Darkening pixels... <img src="http://www.allegro.cc/forums/smileys/rolleyes.gif" alt="::)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (ngiacomelli)</author>
		<pubDate>Wed, 21 Dec 2005 05:51:20 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>You could always make a hint to the compiler by making those two functions inline. Or if you prefer the ugly horrible way, make them macros.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Neil Walker)</author>
		<pubDate>Wed, 21 Dec 2005 14:33:16 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>For 32-bit images:
</p><div class="source-code snippet"><div class="inner"><pre><span class="k1">int</span> c1 <span class="k3">=</span> <a href="http://www.allegro.cc/manual/_getpixel32" target="_blank"><span class="a">_getpixel32</span></a><span class="k2">(</span>image, x, y<span class="k2">)</span><span class="k2">;</span>
<span class="k1">int</span> c2 <span class="k3">=</span> <span class="k2">(</span>c1<span class="k3">&amp;</span><span class="n">0xFF00FF</span><span class="k2">)</span> <span class="k3">*</span> a <span class="k3">/</span> <span class="n">255</span><span class="k2">;</span>
c1 <span class="k3">=</span> <span class="k2">(</span>c1<span class="k3">&amp;</span><span class="n">0xFF00FF00</span><span class="k2">)</span> <span class="k3">*</span> a <span class="k3">/</span> <span class="n">255</span><span class="k2">;</span>
<a href="http://www.allegro.cc/manual/_putpixel32" target="_blank"><span class="a">_putpixel32</span></a><span class="k2">(</span>image, x, y, <span class="k2">(</span>c1<span class="k3">&amp;</span><span class="n">0xFF00FF00</span><span class="k2">)</span> <span class="k3">|</span> <span class="k2">(</span>c2<span class="k3">&amp;</span><span class="n">0xFF00FF</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>Where &#39;a&#39; is the amount to darken between 0 and 255.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kitty Cat)</author>
		<pubDate>Wed, 21 Dec 2005 14:39:44 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Nice trick KC!<br />Here&#39;s one for 16 bpp (565), untested though:
</p><div class="source-code snippet"><div class="inner"><pre><span class="c">// a should be in the range 0...64</span>
<span class="k1">int</span> c <span class="k3">=</span> <a href="http://www.allegro.cc/manual/_getpixel16" target="_blank"><span class="a">_getpixel16</span></a><span class="k2">(</span>image, x, y<span class="k2">)</span><span class="k2">;</span>
<span class="k1">register</span> <span class="k1">int</span> cr <span class="k3">=</span> c <span class="k3">&amp;</span> <span class="n">31</span><span class="k2">;</span>
<span class="k1">register</span> <span class="k1">int</span> cg <span class="k3">=</span> <span class="k2">(</span>c <span class="k3">&gt;</span><span class="k3">&gt;</span> <span class="n">5</span><span class="k2">)</span> <span class="k3">&amp;</span> <span class="n">63</span><span class="k2">;</span>
<span class="k1">register</span> <span class="k1">int</span> cb <span class="k3">=</span> <span class="k2">(</span>c <span class="k3">&gt;</span><span class="k3">&gt;</span> <span class="n">11</span><span class="k2">)</span> <span class="k3">&amp;</span> <span class="n">31</span><span class="k2">;</span>
c <span class="k3">=</span> <span class="k2">(</span><span class="k2">(</span>cr <span class="k3">|</span> <span class="k2">(</span>cb <span class="k3">&lt;</span><span class="k3">&lt;</span> <span class="n">10</span><span class="k2">)</span> <span class="k3">|</span> <span class="k2">(</span>cg <span class="k3">&lt;</span><span class="k3">&lt;</span> <span class="n">20</span><span class="k2">)</span><span class="k2">)</span> <span class="k3">*</span> a<span class="k2">)</span> <span class="k3">&gt;</span><span class="k3">&gt;</span> <span class="n">6</span><span class="k2">;</span>
cr <span class="k3">=</span> c <span class="k3">&amp;</span> <span class="n">31</span><span class="k2">;</span>
cb <span class="k3">=</span> <span class="k2">(</span>c <span class="k3">&gt;</span><span class="k3">&gt;</span> <span class="n">10</span><span class="k2">)</span> <span class="k3">&amp;</span> <span class="n">31</span><span class="k2">;</span>
cg <span class="k3">=</span> <span class="k2">(</span>c <span class="k3">&gt;</span><span class="k3">&gt;</span> <span class="n">20</span><span class="k2">)</span> <span class="k3">&amp;</span> <span class="n">63</span><span class="k2">;</span>
putpixel16<span class="k2">(</span>image, x, y, cr <span class="k3">|</span> <span class="k2">(</span>cg <span class="k3">&lt;</span><span class="k3">&lt;</span> <span class="n">5</span><span class="k2">)</span> <span class="k3">|</span> <span class="k2">(</span>cb <span class="k3">&lt;</span><span class="k3">&lt;</span> <span class="n">11</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Tobias Dammers)</author>
		<pubDate>Wed, 21 Dec 2005 17:01:24 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Actually..<br /><span class="source-code">c1 <span class="k3">=</span> <span class="k2">(</span>c1<span class="k3">&amp;</span><span class="n">0xFF00FF00</span><span class="k2">)</span> <span class="k3">*</span> a <span class="k3">/</span> <span class="n">255</span><span class="k2">;</span></span>just realized that&#39;ll break if the top byte isn&#39;t alpha (the multiply will overflow the value). However, you should be able to do this:<br /><span class="source-code">c1 <span class="k3">=</span> <span class="k2">(</span>c1<span class="k3">&amp;</span><span class="n">0xFF00FF00</span><span class="k2">)</span> <span class="k3">/</span> <span class="n">255</span> <span class="k3">*</span> a<span class="k2">;</span></span>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kitty Cat)</author>
		<pubDate>Wed, 21 Dec 2005 17:16:32 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Hello,<br />Could you explain for simpletons what exactly is going on with the colours in those binary operations. I think you&#39;re getting separately the highest red/blue and green values then I lose it after that <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Neil Walker)</author>
		<pubDate>Wed, 21 Dec 2005 18:48:34 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>KittyCat, that&#39;s awesome!  You just saved me 4 lines of code in my 2.7kb software renderer!</p><p><img src="http://www.allegro.cc/forums/smileys/grin.gif" alt=";D" /></p><p>edit; <a href="http://www.student.kuleuven.ac.be/~m0216922/CG/">Check out this link for the rgb color theory</a>.  Kitty cat&#39;s code adds with saturation (ie multiply by x, if greater than 255, then = 255 or the opposite for 0).  Very cool.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (nonnus29)</author>
		<pubDate>Wed, 21 Dec 2005 18:54:40 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>The trick is that you create 32-bit integer values that contain color components with enough zeroes between them. When you multiply, the zeroes will be filled with the overflow from the multiplication. Then we divide (or R-shift) back and filter the result. Observe:
</p><div class="source-code snippet"><div class="inner"><pre>a <span class="k3">=</span> <span class="n">0x12</span>
b <span class="k3">=</span> <span class="n">0x34</span>
c <span class="k3">=</span> <span class="n">0x1234</span> <span class="c">// this is a packed version with the components a and b.</span>
<span class="c">// my code rearranges it to be something similar to this:</span>
c1 <span class="k3">=</span> <span class="n">0x120034</span>
<span class="c">// Then we can multiply it by 256 for example:</span>
cx256 <span class="k3">=</span> <span class="n">0x12003400</span>
<span class="c">/* Note that the zeroes in c1 are now filled, but that the result from b*256 does not interfere with that from a*256. In fact, we have now executed 2 multiplications with only 1 mul statement.*/</span>
c3 <span class="k3">=</span> <span class="k2">(</span>cx256 <span class="k3">&amp;</span> <span class="n">0xFF00FF00</span><span class="k2">)</span> <span class="k3">/</span> <span class="n">256</span>
c3 <span class="k3">=</span> <span class="n">0x120034</span> <span class="c">// nothing has changed, since we multiplied and then divided by 256.</span>
</pre></div></div><p>
By doing several multiplications in one statement, we can get away with one mul operator. Since multiplication and division are very expensive operations compared to shifts and binary operators, this can save a lot of cpu time.</p><p>My code rearranges the components and adds zeroes between them, so I get away with a single mul. KC&#39;s code decomposes the color int into two values, using 2 muls instead of 3. The downside of my code is that it works only for 16-bit colors, while KC&#39;s version is for 32-bit.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Tobias Dammers)</author>
		<pubDate>Wed, 21 Dec 2005 18:59:36 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Nice tricks you gave.<br />How is it possible that nobody have already make a collection of them for each color depth and make an add for allegro ?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (GullRaDriel)</author>
		<pubDate>Wed, 21 Dec 2005 19:28:29 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>An add-on for Allegro would defeat the purpose of these low-level optimizations <img src="http://www.allegro.cc/forums/smileys/tongue.gif" alt=":P" /> And we have a forum for exchanging cool tricks!
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (CGamesPlay)</author>
		<pubDate>Wed, 21 Dec 2005 19:55:58 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Since multiplication and division are very expensive operations compared to shifts and binary operators
</p></div></div><p>
They&#39;re not that expensive. I don&#39;t think any modern CPU charges more than twice as much for a multiply as a shift, and many charge the same.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Thomas Harte)</author>
		<pubDate>Wed, 21 Dec 2005 21:30:15 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>&gt; They&#39;re not that expensive. I don&#39;t think any modern CPU charges more than twice<br />&gt; as much for a multiply as a shift, and many charge the same.</p><p>When I was doing asm stuff, divides were above 100 cycles.... <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" /><br />Was fun stuff to write though.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (vpenquerch)</author>
		<pubDate>Wed, 21 Dec 2005 21:41:07 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
You could always make a hint to the compiler by making those two functions inline. Or if you prefer the ugly horrible way, make them macros.
</p></div></div><p>

Done!</p><p>I do have a question about making look-up tables for getr, getg, and getb. What&#39;s the easiest method?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (ngiacomelli)</author>
		<pubDate>Wed, 21 Dec 2005 22:24:28 +0000</pubDate>
	</item>
</rss>
