<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>biphenyl.org &#187; Science</title>
	<atom:link href="http://biphenyl.org/blog/category/science/feed/" rel="self" type="application/rss+xml" />
	<link>http://biphenyl.org/blog</link>
	<description>Aromatic, organic, no longer associated with persistent environmental toxins?</description>
	<lastBuildDate>Tue, 01 May 2012 09:04:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Unity3D Surface Shader Tutorial</title>
		<link>http://biphenyl.org/blog/2012/04/24/unity3d-surface-shader-tutorial/</link>
		<comments>http://biphenyl.org/blog/2012/04/24/unity3d-surface-shader-tutorial/#comments</comments>
		<pubDate>Tue, 24 Apr 2012 10:55:51 +0000</pubDate>
		<dc:creator>biphenyl</dc:creator>
				<category><![CDATA[Maps]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Science]]></category>
		<category><![CDATA[Unity]]></category>

		<guid isPermaLink="false">http://biphenyl.org/blog/?p=127</guid>
		<description><![CDATA[I&#8217;ve been meaning to learn about Unity&#8217;s Surface Shader paradigm since I saw Shawn White&#8217;s talk at Unite 2010 (newer 2011 version here). Shawn was our shader and visuals programmer during the Blurst period at Flashbang, so I rarely messed with shaders, but he became something of an expert. I finally got around to trying [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been meaning to learn about Unity&#8217;s Surface Shader paradigm since I saw Shawn White&#8217;s talk at Unite 2010 (newer 2011 version <a href="http://unity3d.com/unite/archive/2011">here</a>). Shawn was our shader and visuals programmer during the Blurst period at Flashbang, so I rarely messed with shaders, but he became something of an expert. I finally got around to trying this out 2 years later and figured I would share the knowledge I gained. Here&#8217;s the final version of what I made, a model of Earth using NASA&#8217;s <a href="http://visibleearth.nasa.gov/view_cat.php?categoryID=1484">Blue Marble Next Generation</a> dataset. Textures are big so it takes a bit to load. Click and move the mouse to rotate the camera. Take a moment to watch how lighting interacts with water (especially rivers), the transition from night lights to daylight along the terminator, and the way that clouds scatter light around the edge. I&#8217;ll explain how each of these effects is achieved below. The <strong>full shader files</strong> are linked at the bottom of the post.</p>
<h3 style="text-align: center;"><strong>Blue Marble Surface Shader Demo</strong></h3>
<p style="text-align: center;"><a href="http://biphenyl.org/projects/BlueMarble/"><img class="size-medium wp-image-130 aligncenter" title="Blue Marble Surface Shader Demo" src="http://biphenyl.org/blog/wp-content/uploads/2012/04/Icon-Big-300x300.png" alt="" width="300" height="300" /></a></p>
<p>Normally shaders are written as two related programs in a single file – a vertex program that modifies vertex data (like position, normals, etc.), followed by a fragment or pixel program that takes interpolated vertex data for a single pixel and converts it into the final output color. This pixel program includes everything that normally makes a shader pretty – texture combines, lighting, etc. It&#8217;s also usually a horrible mess of maths, which can be daunting if you <em>don&#8217;t</em> have a degree in linear algebra. Speaking of which, here&#8217;s a tip when thinking about shaders, which use lots of dot products – <strong>the dot product is basically just the angle between two vectors</strong>, when both of those vectors have length 1. Specifically, a•b = cos(theta). So a•b = 1 =&gt; theta = 0 degrees, a•b = 0 =&gt; theta = 90 degrees, a•b = -1 =&gt; theta = 180 degrees.</p>
<p>The surface shader paradigm abstracts the pixel program into two steps – a <strong>surface program</strong>, that modifies the per-pixel properties of the surface (color, alpha value, surface normal, emissive light color, etc.) and a <strong>lighting program</strong>, that applies the lights to each pixel. This abstraction means that whenever you calculate a surface property, you should think about whether it is dependent on lighting. If yes, the calculation should go in the lighting program. If no, it can go into the surface program.</p>
<h3>Picking Inspirations</h3>
<p>A good way to learn shader programming is to try and emulate an effect you&#8217;ve seen somewhere else. I was interested in making a set of shaders that produced realistic looking planets, but I also specifically liked <a href="http://entitycrisis.blogspot.com/2011/01/unity3d-30-planet-shader.html">rim-lighting effects</a>, and <a href="http://www.flight404.com/blog/?p=325">specular reflections on rivers</a>.</p>
<h3>Property and Program Declarations</h3>
<p>Unity shaders start out with property declarations. These are the properties that will be exposed to the Material inspector and can be modified on a per-material basis. Here are the property declarations for the planet shader:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="glsl" style="font-family:monospace;">Shader <span style="color: #ff0000;">&quot;Custom/Earth&quot;</span> <span style="color: #000066;">&#123;</span>
	Properties <span style="color: #000066;">&#123;</span>
		_MainTex <span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Diffuse(RGB) Spec(A)&quot;</span><span style="color: #000066;">,</span> 2D<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #ff0000;">&quot;white&quot;</span> <span style="color: #000066;">&#123;</span><span style="color: #000066;">&#125;</span>
		_BumpMap <span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Bumpmap&quot;</span><span style="color: #000066;">,</span> 2D<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #ff0000;">&quot;bump&quot;</span> <span style="color: #000066;">&#123;</span><span style="color: #000066;">&#125;</span>
		_EmissionMap<span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Night Lights Map&quot;</span><span style="color: #000066;">,</span> 2D<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #ff0000;">&quot;white&quot;</span> <span style="color: #000066;">&#123;</span><span style="color: #000066;">&#125;</span>
		_EmissionStr<span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Night Lights Strength&quot;</span><span style="color: #000066;">,</span> Range<span style="color: #000066;">&#40;</span><span style="color: #0000ff;">0</span><span style="color: #000066;">,</span><span style="color: #0000ff;">1</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #0000ff;">0.5</span>
		_EmissionColor<span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Night Lights Color&quot;</span><span style="color: #000066;">,</span> Color<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #000066;">&#40;</span><span style="color: #0000ff;">1.0</span><span style="color: #000066;">,</span> <span style="color: #0000ff;">1.0</span><span style="color: #000066;">,</span> <span style="color: #0000ff;">1.0</span><span style="color: #000066;">,</span> <span style="color: #0000ff;">1.0</span><span style="color: #000066;">&#41;</span>
		_SpecColor <span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Specular Color&quot;</span><span style="color: #000066;">,</span> Color<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #000066;">&#40;</span><span style="color: #0000ff;">0.5</span><span style="color: #000066;">,</span><span style="color: #0000ff;">0.5</span><span style="color: #000066;">,</span><span style="color: #0000ff;">0.5</span><span style="color: #000066;">,</span><span style="color: #0000ff;">1</span><span style="color: #000066;">&#41;</span>
		_Shininess <span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Shininess&quot;</span><span style="color: #000066;">,</span> Range <span style="color: #000066;">&#40;</span><span style="color: #0000ff;">0.01</span><span style="color: #000066;">,</span> <span style="color: #0000ff;">1</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #0000ff;">0.078125</span>
		_SpecPower <span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Specular Power&quot;</span><span style="color: #000066;">,</span> Float<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #0000ff;">48.0</span>
	<span style="color: #000066;">&#125;</span>
	SubShader <span style="color: #000066;">&#123;</span>
		Tags <span style="color: #000066;">&#123;</span> <span style="color: #ff0000;">&quot;RenderType&quot;</span> <span style="color: #000066;">=</span> <span style="color: #ff0000;">&quot;Opaque&quot;</span> <span style="color: #000066;">&#125;</span>
		CGPROGRAM
		<span style="color: #009900;">#pragma surface surf PlanetSpecular noambient</span>
		<span style="color: #000066;">...</span>
		<span style="color: #006600;">ENDCG</span>
	<span style="color: #000066;">&#125;</span>
	Fallback <span style="color: #ff0000;">&quot;Diffuse&quot;</span>
<span style="color: #000066;">&#125;</span></pre></td></tr></table></div>

<p>Each property has a <strong>name</strong> (which is the variable name in the Cg code, as well as the material property name in Unity), a <strong>description</strong>, a <strong>type</strong> (2D for textures, Range for sliders, Float for type-in values, etc.), and a <strong>default value</strong>. The first three in the example above are textures supplied to the shader, the others are colors or floating point values that give us knobs to turn to change the shader look. Here&#8217;s what the inspector for this shader ends up as:</p>
<p><a href="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-24-at-03.50.32.png"><img class="alignnone size-medium wp-image-182" title="Planet Shader Inspector" src="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-24-at-03.50.32-231x300.png" alt="" width="231" height="300" /></a></p>
<p>The actual Cg shader code goes within the Subshader{} block, between CGPROGRAM and ENDCG. The separate Pass{} blocks, which are normally used when writing fragment shaders, are generated automatically by the shader compiler – that&#8217;s the beauty of this higher abstraction level. The <strong>#pragma surface &#8230;</strong> line tells the compiler that we&#8217;re writing a surface shader, and then tells it the names of our surface function (<strong>surf</strong>) and lighting model (<strong>PlanetSpecular</strong>). There are two built-in lighting models, Lambert (Diffuse) and BlinnPhong (Specular). If we give any other value, the surface shader will expect us to write that lighting function as well. The <strong>noambient</strong> part at the end is an optional parameter that instructs it not to apply scene-based ambient lighting. There are several other optional parameters, which are in the <a href="http://unity3d.com/support/documentation/Components/SL-SurfaceShaders.html">Surface Shader documentation</a>. The <strong>Fallback &#8220;Diffuse&#8221;</strong> at the end of the shader tells it which shader to use if the current platform doesn&#8217;t support the shader we write. In fact simple Diffuse would not be a good fallback for this shader, so I should later change it to one that includes specular highlighting.</p>
<h3>Surface Program</h3>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="glsl" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">struct</span> Input <span style="color: #000066;">&#123;</span>
	float2 uv_MainTex<span style="color: #000066;">;</span>
	float2 uv_BumpMap<span style="color: #000066;">;</span>
	float2 uv_EmissionMap<span style="color: #000066;">;</span>
<span style="color: #000066;">&#125;</span><span style="color: #000066;">;</span>
<span style="color: #000066; font-weight: bold;">sampler2D</span> _MainTex<span style="color: #000066;">;</span>
<span style="color: #000066; font-weight: bold;">sampler2D</span> _BumpMap<span style="color: #000066;">;</span>
<span style="color: #000066; font-weight: bold;">sampler2D</span> _EmissionMap<span style="color: #000066;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">void</span> surf <span style="color: #000066;">&#40;</span>Input IN<span style="color: #000066;">,</span> <span style="color: #333399; font-weight: bold;">inout</span> SurfaceOutput o<span style="color: #000066;">&#41;</span> <span style="color: #000066;">&#123;</span>
	o<span style="color: #000066;">.</span><span style="color: #006600;">Albedo</span> <span style="color: #000066;">=</span> tex2D <span style="color: #000066;">&#40;</span>_MainTex<span style="color: #000066;">,</span> IN<span style="color: #000066;">.</span><span style="color: #006600;">uv_MainTex</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">.</span><span style="color: #006600;">rgb</span><span style="color: #000066;">;</span>
	o<span style="color: #000066;">.</span><span style="color: #006600;">Specular</span> <span style="color: #000066;">=</span> tex2D <span style="color: #000066;">&#40;</span>_MainTex<span style="color: #000066;">,</span> IN<span style="color: #000066;">.</span><span style="color: #006600;">uv_MainTex</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">.</span><span style="color: #006600;">a</span><span style="color: #000066;">;</span>
	o<span style="color: #000066;">.</span><span style="color: #006600;">Normal</span> <span style="color: #000066;">=</span> UnpackNormal <span style="color: #000066;">&#40;</span>tex2D <span style="color: #000066;">&#40;</span>_BumpMap<span style="color: #000066;">,</span> IN<span style="color: #000066;">.</span><span style="color: #006600;">uv_BumpMap</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
	o<span style="color: #000066;">.</span><span style="color: #006600;">Alpha</span> <span style="color: #000066;">=</span> <span style="color: #993333; font-weight: bold;">length</span><span style="color: #000066;">&#40;</span>tex2D <span style="color: #000066;">&#40;</span>_EmissionMap<span style="color: #000066;">,</span> IN<span style="color: #000066;">.</span><span style="color: #006600;">uv_EmissionMap</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">.</span><span style="color: #006600;">rgb</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
<span style="color: #000066;">&#125;</span></pre></td></tr></table></div>

<p>This is the surface program, which comes after the <strong>#pragma surface &#8230;</strong> line above. It has three parts – definition of the <strong>input structure</strong> (i.e. what data we want per-pixel), <strong>variable declarations</strong> of the material-wide (non per-pixel) properties we want to use, and the <strong>surface function </strong>(<strong>surf</strong>), which we named in the <strong>#pragma surface &#8230;</strong> line.</p>
<p>The <strong>input structure</strong> is any set of values that we want on a per-pixel basis. Usually this should include the uv coordinates of your input textures, named <strong>uv</strong> (or <strong>uv2</strong> for the second coordinate set) followed by the texture name from the property definitions. The input structure can also contain some built-in values such as <strong>viewDir</strong> (the direction to the camera). The full list is again on the <a href="http://unity3d.com/support/documentation/Components/SL-SurfaceShaders.html">Surface Shader documentation</a> page.</p>
<p>Next come <strong>variable declarations</strong> for per-material data. This includes the texture samplers for texture properties (remember, the shader loads the texture only once, and then samples it using the uv coordinates per-pixel), which are named the same as the properties. It also includes any per-material constants that will be applied before lighting, such as thresholding values.</p>
<p>The <strong>surface function</strong> is where the actual per-pixel, pre-lighting surface property calculations are done, and stored in the <strong>output structure</strong>. The output structure is the data that will be passed to the lighting model. The default structure is:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="glsl" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">struct</span> SurfaceOutput <span style="color: #000066;">&#123;</span>
    half3 Albedo<span style="color: #000066;">;</span>
    half3 Normal<span style="color: #000066;">;</span>
    half3 Emission<span style="color: #000066;">;</span>
    <span style="color: #000066; font-weight: bold;">half</span> Specular<span style="color: #000066;">;</span>
    <span style="color: #000066; font-weight: bold;">half</span> Gloss<span style="color: #000066;">;</span>
    <span style="color: #000066; font-weight: bold;">half</span> Alpha<span style="color: #000066;">;</span>
<span style="color: #000066;">&#125;</span><span style="color: #000066;">;</span></pre></td></tr></table></div>

<p>While each of these have a specific meaning if you use the standard lighting models, you can think of them as simply three 3-vectors and three numbers where data can be stored. Some of them have specific semantic meanings in certain cases – for instance, <strong>Emission</strong> always appears to be combined with other lights <em>before</em> being passed to the lighting model (you can still access its value in your custom lighting function, but its value will also be added to other lights in the scene). Likewise <strong>Alpha</strong> has a specific meaning for alpha-blended shaders (like the Clouds shader below).</p>
<p>In the surface function for the Earth shader, I simply store the <strong>surface color</strong> in the <strong>Albedo</strong> variable, the <strong>surface specular reflectance</strong> (alpha channel of _MainTex) in the <strong>Specular</strong> variable, the <strong>surface normal </strong>vector in the <strong>Normal</strong> variable, and the <strong>emissive light</strong> (city night lights) in the <strong>Alpha</strong> variable. Two things to note here:<br />
1) I stored the surface emissive light in Alpha instead of Emission because I can then control the strength of the surface lights based on other scene lights – i.e. I can turn off night lights when a pixel is illuminated by the Sun. If it had stored the emissive light in Emission, it would have been combined with the scene lights <em>before</em> being passed to the lighting model, and I would not have been able to control the two independently.<br />
2) Right now, the shader uses three texture samplers – _MainTex for albedo and specularity, _BumpMap for surface normals, and _EmissionMap for the city lights. This is wasteful, since I only use the grayscale value of _EmissionMap. Instead, it might be smarter to pack the city lights into the alpha channel of _BumpMap. This would reduce to only two texture samplers, using both rgb and a values of each.</p>
<h3>Lighting Program</h3>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="glsl" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">float</span> _Shininess<span style="color: #000066;">;</span>
<span style="color: #000066; font-weight: bold;">float</span> _SpecPower<span style="color: #000066;">;</span>
<span style="color: #000066; font-weight: bold;">float</span> _EmissionStr<span style="color: #000066;">;</span>
half4 _EmissionColor<span style="color: #000066;">;</span>
&nbsp;
half4 LightingPlanetSpecular <span style="color: #000066;">&#40;</span>SurfaceOutput s<span style="color: #000066;">,</span> half3 lightDir<span style="color: #000066;">,</span> half3 viewDir<span style="color: #000066;">,</span> <span style="color: #000066; font-weight: bold;">half</span> atten<span style="color: #000066;">&#41;</span> <span style="color: #000066;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">half</span> diffuse <span style="color: #000066;">=</span> <span style="color: #993333; font-weight: bold;">max</span> <span style="color: #000066;">&#40;</span><span style="color: #0000ff;">0</span><span style="color: #000066;">,</span> <span style="color: #993333; font-weight: bold;">dot</span> <span style="color: #000066;">&#40;</span>s<span style="color: #000066;">.</span><span style="color: #006600;">Normal</span><span style="color: #000066;">,</span> lightDir<span style="color: #000066;">&#41;</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
	half3 lightView <span style="color: #000066;">=</span> <span style="color: #993333; font-weight: bold;">normalize</span> <span style="color: #000066;">&#40;</span>lightDir <span style="color: #000066;">+</span> viewDir<span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
	<span style="color: #000066; font-weight: bold;">float</span> specStr <span style="color: #000066;">=</span> <span style="color: #993333; font-weight: bold;">max</span> <span style="color: #000066;">&#40;</span><span style="color: #0000ff;">0</span><span style="color: #000066;">,</span> <span style="color: #993333; font-weight: bold;">dot</span><span style="color: #000066;">&#40;</span>s<span style="color: #000066;">.</span><span style="color: #006600;">Normal</span><span style="color: #000066;">,</span> lightView<span style="color: #000066;">&#41;</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
	<span style="color: #000066; font-weight: bold;">float</span> spec <span style="color: #000066;">=</span> <span style="color: #993333; font-weight: bold;">pow</span> <span style="color: #000066;">&#40;</span>specStr<span style="color: #000066;">,</span> _SpecPower<span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
	half4 c<span style="color: #000066;">;</span>
	c<span style="color: #000066;">.</span><span style="color: #006600;">rgb</span> <span style="color: #000066;">=</span> _LightColor0<span style="color: #000066;">.</span><span style="color: #006600;">rgb</span> <span style="color: #000066;">*</span> <span style="color: #000066;">&#40;</span>atten <span style="color: #000066;">*</span> <span style="color: #0000ff;">2</span><span style="color: #000066;">&#41;</span> <span style="color: #000066;">*</span> <span style="color: #000066;">&#40;</span>s<span style="color: #000066;">.</span><span style="color: #006600;">Albedo</span> <span style="color: #000066;">*</span> diffuse <span style="color: #000066;">+</span>
		spec <span style="color: #000066;">*</span> s<span style="color: #000066;">.</span><span style="color: #006600;">Specular</span> <span style="color: #000066;">*</span> _Shininess <span style="color: #000066;">*</span> _SpecColor<span style="color: #000066;">&#41;</span> <span style="color: #000066;">+</span>
		<span style="color: #000066;">&#40;</span>saturate<span style="color: #000066;">&#40;</span><span style="color: #0000ff;">1.0</span><span style="color: #000066;">-</span><span style="color: #0000ff;">2</span><span style="color: #000066;">*</span>diffuse<span style="color: #000066;">&#41;</span> <span style="color: #000066;">*</span> s<span style="color: #000066;">.</span><span style="color: #006600;">Alpha</span> <span style="color: #000066;">*</span> _EmissionStr <span style="color: #000066;">*</span> _EmissionColor<span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
	c<span style="color: #000066;">.</span><span style="color: #006600;">a</span> <span style="color: #000066;">=</span> s<span style="color: #000066;">.</span><span style="color: #006600;">Specular</span><span style="color: #000066;">;</span>
	<span style="color: #000000; font-weight: bold;">return</span> c<span style="color: #000066;">;</span>
<span style="color: #000066;">&#125;</span></pre></td></tr></table></div>

<p>For this shader, this is where the magic happens. The first thing I do is declare the <strong>material property variables</strong>. In this case it&#8217;s three floats – two that control the specular reflection (_Shininess and _SpecPower) and one that controls the intensity of the night lights (_EmissionStr).</p>
<p>The lighting function is named based on the lighting model name you supply in the <strong>#pragma surface &#8230;</strong> line. The default lighting function is simply Lighting&lt;ModelName&gt;, so in this case LightingPlanetSpecular. There are variants of this function signature based on whether or not the lighting model is view direction dependent (specular reflection is), as well as whether or not the shader works with deferred lighting, or needs to handle directional lightmaps. These are detailed on the <a href="http://unity3d.com/support/documentation/Components/SL-SurfaceShaderLighting.html">Surface Shader Lighting Models</a> page.</p>
<p>The per-pixel inputs to the lighting model function are the <strong>surface property structure</strong> from the surface program (<strong>SurfaceOutput s</strong>), the vector <strong>direction to the light</strong> (<strong>half3 lightDir</strong>), the vector <strong>view direction</strong> (<strong>half3 viewDir</strong>), and the <strong>lighting attenuation factor</strong> (<strong>half atten</strong>). The output of the lighting model is a half4 vector – the final RGBA color of the rendered pixel.</p>
<p>In the PlanetSpecular lighting model above, line 7 calculates the diffuse emission  factor per-pixel, which ranges from 0 to 1. Lines 8-10 calculate the specular emission factor per-pixel, using the <a href="http://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model">Blinn-Phong algorithm</a>, which again ranges from 0 to 1.</p>
<p>Line 12 is where I set the final output color for the pixel. It is composed of the <strong>diffuse color term</strong> (_LightColor0 * 2 * atten * diffuse * s.Albedo), the <strong>specular color term</strong> (_LightColor0 * 2 * atten * spec * _Shininess * _SpecColor), and an <strong>emissive color term</strong> (saturate(1 &#8211; 2 * diffuse) * s.Alpha * _EmissionStr * _EmissionColor) for the night lights. Again, the diffuse and specular terms are totally standard Blinn-Phong. That&#8217;s it!</p>
<h3>Night Lights</h3>
<p>For the night lights, saturate(1 &#8211; 2 * diffuse) serves as the strength of the lights for the pixel, where saturate() is a <a href="http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html">Cg function</a> that clamps a value between 0 and 1. It&#8217;s necessary so that you don&#8217;t get negative emissive lighting (black cities) when the diffuse term is 0.5-1. I used 1 &#8211; 2 * diffuse because I wanted the lights to turn on gradually as a city neared the terminator between daylight and night. Using only 1 &#8211; diffuse meant that lights would begin to turn on as soon as a city passed local noon, which looked unnatural (actually the 2 should probably be a tunable material property). By the time a city reaches the terminator, the diffuse term is 0 and the lights are fully on.</p>
<div id="attachment_166" class="wp-caption aligncenter" style="width: 310px"><a href="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-24-at-02.57.20.png"><img class="size-medium wp-image-166 aligncenter" title="Fading Lights" src="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-24-at-02.57.20-300x300.png" alt="" width="300" height="300" /></a><p class="wp-caption-text">Night lights slowly fade as cities pass the day/night boundary</p></div>
<p>&nbsp;</p>
<h3>Emphasizing River Specular Reflection</h3>
<p>I loved the look of the Amazon in the Flight404 example above, so I played around with the specular map (stored in the alpha channel of _MainTex), until I got an effect I liked. I eventually settled on selecting water using a <a href="http://naturalearth.springercarto.com/ne3_data/8192/textures/2_no_clouds_8k.jpg">false color map</a>, the same one used for the Flight404 example. I used Photoshop&#8217;s Select Color Range tool to pick the water color, with the fuzziness cranked all the way up. I then ran an edge detection filter to emphasize the rivers. This also had the side effect of emphasizing shorelines, a subtle but really cool effect. I picked a silver-blue color for _SpecColor that contrasts well with the dark.</p>
<div id="attachment_167" class="wp-caption aligncenter" style="width: 310px"><a href="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-24-at-03.02.18.png"><img class="size-medium wp-image-167" title="Amazon Reflection" src="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-24-at-03.02.18-300x246.png" alt="" width="300" height="246" /></a><p class="wp-caption-text">River specular reflection on the Amazon. It&#39;s more subtle than the Flight404 example, but still stunning. The shoreline is also emphasized thanks to the edge detection filter I applied to the spec map.</p></div>
<h3>Cloud Shader</h3>
<p>I wanted the cloud shader to approximate subsurface scattering in the atmosphere, like in the rim lighting planet shader in the inspirations section above. I didn&#8217;t like two things about basic rim lighting though – it is applied equally around the entire rim, and for shaders with bump maps (like the example one I linked), it looks ugly as all hell. So in the spirit of learning, I decided to write a custom shader for this, too. Here it is:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
</pre></td><td class="code"><pre class="glsl" style="font-family:monospace;">Shader <span style="color: #ff0000;">&quot;Custom/Clouds&quot;</span> <span style="color: #000066;">&#123;</span>
	Properties <span style="color: #000066;">&#123;</span>
		_MainTex <span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Alpha (A)&quot;</span><span style="color: #000066;">,</span> 2D<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #ff0000;">&quot;white&quot;</span> <span style="color: #000066;">&#123;</span><span style="color: #000066;">&#125;</span>
		_RimColor <span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Rim Color&quot;</span><span style="color: #000066;">,</span> Color<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #000066;">&#40;</span><span style="color: #0000ff;">0.26</span><span style="color: #000066;">,</span><span style="color: #0000ff;">0.19</span><span style="color: #000066;">,</span><span style="color: #0000ff;">0.16</span><span style="color: #000066;">,</span><span style="color: #0000ff;">0.0</span><span style="color: #000066;">&#41;</span>
		_RimPower <span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Rim Power&quot;</span><span style="color: #000066;">,</span> Float<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #0000ff;">3.0</span>
	<span style="color: #000066;">&#125;</span>
	SubShader <span style="color: #000066;">&#123;</span>
		Tags <span style="color: #000066;">&#123;</span> <span style="color: #ff0000;">&quot;RenderType&quot;</span><span style="color: #000066;">=</span><span style="color: #ff0000;">&quot;Transparent&quot;</span> <span style="color: #000066;">&#125;</span>
&nbsp;
		CGPROGRAM
		<span style="color: #009900;">#pragma surface surf WrapLambert alpha</span>
&nbsp;
		<span style="color: #000066; font-weight: bold;">struct</span> Input <span style="color: #000066;">&#123;</span>
			float2 uv_MainTex<span style="color: #000066;">;</span>
			float3 viewDir<span style="color: #000066;">;</span>
		<span style="color: #000066;">&#125;</span><span style="color: #000066;">;</span>
		<span style="color: #000066; font-weight: bold;">sampler2D</span> _MainTex<span style="color: #000066;">;</span>
		<span style="color: #000066; font-weight: bold;">float</span> _RimPower<span style="color: #000066;">;</span>
&nbsp;
		<span style="color: #000066; font-weight: bold;">void</span> surf <span style="color: #000066;">&#40;</span>Input IN<span style="color: #000066;">,</span> <span style="color: #333399; font-weight: bold;">inout</span> SurfaceOutput o<span style="color: #000066;">&#41;</span> <span style="color: #000066;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">half</span> rim <span style="color: #000066;">=</span> <span style="color: #0000ff;">1.0</span> <span style="color: #000066;">-</span> saturate<span style="color: #000066;">&#40;</span><span style="color: #993333; font-weight: bold;">dot</span> <span style="color: #000066;">&#40;</span><span style="color: #993333; font-weight: bold;">normalize</span><span style="color: #000066;">&#40;</span>IN<span style="color: #000066;">.</span><span style="color: #006600;">viewDir</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">,</span> o<span style="color: #000066;">.</span><span style="color: #006600;">Normal</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
			o<span style="color: #000066;">.</span><span style="color: #006600;">Specular</span> <span style="color: #000066;">=</span> <span style="color: #993333; font-weight: bold;">pow</span> <span style="color: #000066;">&#40;</span>rim<span style="color: #000066;">,</span> _RimPower<span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
			o<span style="color: #000066;">.</span><span style="color: #006600;">Alpha</span> <span style="color: #000066;">=</span> tex2D <span style="color: #000066;">&#40;</span>_MainTex<span style="color: #000066;">,</span> IN<span style="color: #000066;">.</span><span style="color: #006600;">uv_MainTex</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">.</span><span style="color: #006600;">a</span> <span style="color: #000066;">+</span> o<span style="color: #000066;">.</span><span style="color: #006600;">Specular</span><span style="color: #000066;">;</span>
		<span style="color: #000066;">&#125;</span>
		half4 _RimColor<span style="color: #000066;">;</span>
&nbsp;
		half4 LightingWrapLambert <span style="color: #000066;">&#40;</span>SurfaceOutput s<span style="color: #000066;">,</span> half3 lightDir<span style="color: #000066;">,</span> <span style="color: #000066; font-weight: bold;">half</span> atten<span style="color: #000066;">&#41;</span> <span style="color: #000066;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">half</span> NdotL <span style="color: #000066;">=</span> <span style="color: #993333; font-weight: bold;">dot</span> <span style="color: #000066;">&#40;</span>s<span style="color: #000066;">.</span><span style="color: #006600;">Normal</span><span style="color: #000066;">,</span> lightDir<span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
			<span style="color: #000066; font-weight: bold;">half</span> diffuse <span style="color: #000066;">=</span> <span style="color: #993333; font-weight: bold;">max</span><span style="color: #000066;">&#40;</span><span style="color: #0000ff;">0</span><span style="color: #000066;">,</span> NdotL<span style="color: #000066;">*</span> <span style="color: #0000ff;">0.9</span> <span style="color: #000066;">+</span> <span style="color: #0000ff;">0.1</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
			half4 c<span style="color: #000066;">;</span>
			c<span style="color: #000066;">.</span><span style="color: #006600;">rgb</span> <span style="color: #000066;">=</span> <span style="color: #000066;">&#40;</span>atten <span style="color: #000066;">*</span> <span style="color: #0000ff;">2</span><span style="color: #000066;">&#41;</span> <span style="color: #000066;">*</span> _LightColor0<span style="color: #000066;">.</span><span style="color: #006600;">rgb</span> <span style="color: #000066;">*</span> diffuse <span style="color: #000066;">*</span> <span style="color: #000066;">&#40;</span><span style="color: #0000ff;">1.0</span> <span style="color: #000066;">-</span> s<span style="color: #000066;">.</span><span style="color: #006600;">Specular</span><span style="color: #000066;">&#41;</span>
				<span style="color: #000066;">+</span> <span style="color: #000066;">&#40;</span>diffuse <span style="color: #000066;">*</span> s<span style="color: #000066;">.</span><span style="color: #006600;">Specular</span> <span style="color: #000066;">*</span> _RimColor<span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
			c<span style="color: #000066;">.</span><span style="color: #006600;">a</span> <span style="color: #000066;">=</span> s<span style="color: #000066;">.</span><span style="color: #006600;">Alpha</span><span style="color: #000066;">;</span>
			<span style="color: #000000; font-weight: bold;">return</span> c<span style="color: #000066;">;</span>
		<span style="color: #000066;">&#125;</span>
		ENDCG
	<span style="color: #000066;">&#125;</span>
	FallBack <span style="color: #ff0000;">&quot;Diffuse&quot;</span>
<span style="color: #000066;">&#125;</span></pre></td></tr></table></div>

<p>And here is the inspector:</p>
<p><a href="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-24-at-03.50.56.png"><img class="alignnone size-medium wp-image-183" title="Cloud Shader Inspector" src="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-24-at-03.50.56-300x180.png" alt="" width="300" height="180" /></a></p>
<p>There are a few specific interesting things about this shader.</p>
<p>First, it&#8217;s an alpha blended shader (<strong>#pragma surface &#8230; alpha</strong>). In surface shader parlance, this means that all we have to do is fill o.Alpha with the proper alpha value for the pixel and Unity will handle the actual blending. Cool, but it does mean we have to be careful about what we put in that variable.</p>
<p>Second, the rim-lighting calculation. Lines 21-22 are the standard way to do this – it&#8217;s based on the view direction (always around the edges from where we look), and increases in power as the surface normal points sideways from us, hence the 1.0 &#8211; dot(IN.viewDir, o.Normal). I store the value in o.Specular because I want to use lighting to later modify its visibility, so there isn&#8217;t rim light around the entire planet.</p>
<p>Third, the alpha value. I get the alpha value from the supplied _MainTex, but then I add o.Specular, because I want to make the rim lighting visible even if there aren&#8217;t clouds in a pixel (i.e. the alpha from _MainTex is 0).</p>
<p>Fourth, the lighting model is not a standard Lambert (diffuse) model, but is based on Wrapped Lambert, a modified diffuse shader where light is allowed to wrap around the edges of a surface. This again helps to fake subsurface scattering, because it lets the sunlight from the scene wrap slightly around Earth&#8217;s limb. Line 29 is where this happens, and we basically just take 90% of the normal diffuse factor, then add 10%. When we actually apply the lighting, we have a <strong>diffuse term</strong> (2 * atten * _LightColor0.rgb * diffuse * (1.0 &#8211; s.Specular)) and the <strong>emissive term</strong> (diffuse * s.Specular * _RimColor). By multiplying the rim factor (s.Specular) by the diffuse factor, I ensure that we only apply rim lighting where there is normally light. We just add some sky blue for scattered light if we happen to be looking through the atmosphere sideways. The diffuse term gets multiplied by 1.0 &#8211; s.Specular so that rim lighting always takes precedence, otherwise we would just get white light when a brightly lighted limb had the rim lighting added.</p>
<div id="attachment_168" class="wp-caption aligncenter" style="width: 236px"><a href="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-24-at-03.18.23.png"><img class="size-full wp-image-168" title="Clouds Rim Lighting" src="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-24-at-03.18.23.png" alt="" width="226" height="218" /></a><p class="wp-caption-text">Rim lighting on the cloud shader, to fake atmospheric scattering.</p></div>
<p>The end result of the rim lighting is decent, but I don&#8217;t like the hard edge between the limb and black space. This could be fixed by using a ramp texture for the rim lighting, where it slowly increases in intensity from center to limb, then falls off abruptly to simulate thinning atmosphere. That will be a test for another day though!</p>
<h3>Update! Using a Ramp Texture For Rim Lighting</h3>
<p>As I mentioned above I wasn&#8217;t totally pleased with how the rim lighting looked. Since its strength was 100% at the edge, it looked too stark against the black of space. Earth&#8217;s real atmosphere is very thin and quickly fades to nothingness if you look at the horizon from space. So instead of the mathematical power-law that I was using, I replaced the clouds surface function with one that uses a &#8220;ramp texture&#8221; to map viewDir•normal to actual opacity. This lets the artist (me!) pick any gradient that looks good, rather than just changing the power law index.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="glsl" style="font-family:monospace;"><span style="color: #000066;">...</span>
<span style="color: #006600;">Properties</span> <span style="color: #000066;">&#123;</span>
	_MainTex <span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Alpha (A)&quot;</span><span style="color: #000066;">,</span> 2D<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #ff0000;">&quot;white&quot;</span> <span style="color: #000066;">&#123;</span><span style="color: #000066;">&#125;</span>
	_AtmosRamp <span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Atmosphere Ramp (RG or B)&quot;</span><span style="color: #000066;">,</span> 2D<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #ff0000;">&quot;black&quot;</span> <span style="color: #000066;">&#123;</span><span style="color: #000066;">&#125;</span>
	_RimColor <span style="color: #000066;">&#40;</span><span style="color: #ff0000;">&quot;Rim Color&quot;</span><span style="color: #000066;">,</span> Color<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> <span style="color: #000066;">&#40;</span><span style="color: #0000ff;">0.26</span><span style="color: #000066;">,</span><span style="color: #0000ff;">0.19</span><span style="color: #000066;">,</span><span style="color: #0000ff;">0.16</span><span style="color: #000066;">,</span><span style="color: #0000ff;">0.0</span><span style="color: #000066;">&#41;</span>
<span style="color: #000066;">&#125;</span>
<span style="color: #000066;">...</span>
<span style="color: #000066; font-weight: bold;">struct</span> Input <span style="color: #000066;">&#123;</span>
	float2 uv_MainTex<span style="color: #000066;">;</span>
	float3 viewDir<span style="color: #000066;">;</span>
<span style="color: #000066;">&#125;</span><span style="color: #000066;">;</span>
<span style="color: #000066; font-weight: bold;">sampler2D</span> _MainTex<span style="color: #000066;">;</span>
<span style="color: #000066; font-weight: bold;">sampler2D</span> _AtmosRamp<span style="color: #000066;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">void</span> surf <span style="color: #000066;">&#40;</span>Input IN<span style="color: #000066;">,</span> <span style="color: #333399; font-weight: bold;">inout</span> SurfaceOutput o<span style="color: #000066;">&#41;</span> <span style="color: #000066;">&#123;</span>
	float2 uv_Ramp <span style="color: #000066;">=</span> <span style="color: #0000ff;">1.0</span> <span style="color: #000066;">-</span> saturate<span style="color: #000066;">&#40;</span><span style="color: #993333; font-weight: bold;">dot</span> <span style="color: #000066;">&#40;</span><span style="color: #993333; font-weight: bold;">normalize</span><span style="color: #000066;">&#40;</span>IN<span style="color: #000066;">.</span><span style="color: #006600;">viewDir</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">,</span> o<span style="color: #000066;">.</span><span style="color: #006600;">Normal</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">;</span>
	o<span style="color: #000066;">.</span><span style="color: #006600;">Specular</span> <span style="color: #000066;">=</span> tex2D <span style="color: #000066;">&#40;</span>_AtmosRamp<span style="color: #000066;">,</span> uv_Ramp<span style="color: #000066;">&#41;</span><span style="color: #000066;">.</span><span style="color: #006600;">r</span><span style="color: #000066;">;</span>
	o<span style="color: #000066;">.</span><span style="color: #006600;">Alpha</span> <span style="color: #000066;">=</span> tex2D <span style="color: #000066;">&#40;</span>_MainTex<span style="color: #000066;">,</span> IN<span style="color: #000066;">.</span><span style="color: #006600;">uv_MainTex</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">.</span><span style="color: #006600;">a</span> <span style="color: #000066;">+</span> o<span style="color: #000066;">.</span><span style="color: #006600;">Specular</span><span style="color: #000066;">;</span>
<span style="color: #000066;">&#125;</span>
<span style="color: #000066;">...</span></pre></td></tr></table></div>

<p>Line 16 generates the UV coordinate where we sample the ramp texture (this syntax makes both u and v coordinates the same, but the texture is the same on every line in the y direction). Here&#8217;s the inspector:</p>
<div id="attachment_190" class="wp-caption alignnone" style="width: 310px"><a href="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-25-at-02.18.27.png"><img class="size-medium wp-image-190 " title="Ramp Texture Cloud Shader Inspector" src="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-25-at-02.18.27-300x235.png" alt="" width="300" height="235" /></a><p class="wp-caption-text">Inspector for the new ramp texture atmosphere and clouds shader.</p></div>
<p>This looks much, much nicer, and can be tuned easily by simply using a different gradient in the texture. I also gave the sphere model an upgrade with more triangles, so it doesn&#8217;t look so ugly on the edge! Here&#8217;s a comparison to the above picture that used just power-law rim lighting:</p>
<div id="attachment_191" class="wp-caption alignnone" style="width: 250px"><a href="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-25-at-02.17.48.png"><img class="size-full wp-image-191" title="Ramp Texture Atmosphere" src="http://biphenyl.org/blog/wp-content/uploads/2012/04/Screen-Shot-2012-04-25-at-02.17.48.png" alt="" width="240" height="214" /></a><p class="wp-caption-text">Atmosphere using a ramp texture with an abrupt falloff at the edge</p></div>
<p><a href="http://biphenyl.org/blog/content/files/Planet.shader">Full Planet Shader</a><br />
<a href="http://biphenyl.org/blog/content/files/Clouds.shader">Full Cloud Shader</a></p>
<h3>Useful Surface Shader Learning Links</h3>
<p><a href="http://unity3d.com/support/documentation/Components/SL-SurfaceShaders.html">Unity Manual: Writing Surface Shaders</a> – Includes all the #pragma surface optional flags</p>
<p><a href="http://unity3d.com/support/documentation/Components/SL-SurfaceShaderLighting.html">Unity Manual: Surface Shader Lighting</a> – Very brief, but gives naming conventions for lighting functions</p>
<p><a href="http://unity3d.com/support/documentation/Components/SL-SurfaceShaderExamples.html">Unity Manual: Surface Shader Examples</a> – Some good examples but on a rather boring model</p>
<p><a href="http://unity3d.com/support/documentation/Components/SL-SurfaceShaderLightingExamples.html">Unity Manual: Surface Shader Lighting Examples</a> – Good examples for lighting models (toon ramp for instance)</p>
<p><a href="http://unity3d.com/support/documentation/Components/SL-BuiltinValues.html">Unity Manual: ShaderLab Bultin Values</a> – some predefined variables you can use in Cg programs</p>
<p><a href="http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html">Cg Tutorial: Standard Library Functions</a> – Cg functions you can use in your shaders. Note that noise() doesn&#8217;t work in Unity?</p>
<p><a href="http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter05.html">Cg Tutorial: Lighting and Lighting Models</a> – For more information on lighting models</p>
<p><a href="http://www.flight404.com/blog/">Flight 404</a> – Rad visualization porn for inspiration</p>
]]></content:encoded>
			<wfw:commentRss>http://biphenyl.org/blog/2012/04/24/unity3d-surface-shader-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Accuracy in Labeling &#8212; Supernovae</title>
		<link>http://biphenyl.org/blog/2010/03/23/accuracy-in-labeling-supernovae/</link>
		<comments>http://biphenyl.org/blog/2010/03/23/accuracy-in-labeling-supernovae/#comments</comments>
		<pubDate>Tue, 23 Mar 2010 08:21:51 +0000</pubDate>
		<dc:creator>biphenyl</dc:creator>
				<category><![CDATA[Astronomy]]></category>
		<category><![CDATA[Operation Mindfuck]]></category>
		<category><![CDATA[Science]]></category>

		<guid isPermaLink="false">http://biphenyl.org/blog/?p=91</guid>
		<description><![CDATA[Last September I started a PhD in Astrophysics at Arizona State. I really enjoy doing public outreach and engaging in informal education, so as I learn new and awe-inspiring things I spend a lot of time thinking, &#8220;What&#8217;s so cool about this, and how do I explain it to my mother?&#8221; I think Carl Sagan [...]]]></description>
			<content:encoded><![CDATA[<p>Last September I started a PhD in Astrophysics at Arizona State. I really enjoy doing public outreach and engaging in informal education, so as I learn new and awe-inspiring things I spend a lot of time thinking, &#8220;What&#8217;s so cool about this, and how do I explain it to my mother?&#8221; I think Carl Sagan expressed the motivation best in <a href="http://www.amazon.com/Demon-Haunted-World-Science-Candle-Dark/dp/0345409469">The Demon-Haunted World</a>: &#8220;Not explaining science seems to me perverse. When you&#8217;re in love, you want to tell the world.&#8221; What set Carl apart, however, was his unique ability to articulate this love in a way that expressed his enthusiasm and was understandable to a wide audience. Your mother probably doesn&#8217;t want to sit through a stuffy lecture, even if the contents are astounding.</p>
<p>One of the most amazing discoveries of modern astrophysics is that almost all of the chemical elements we see around us were produced in <a href="http://en.wikipedia.org/wiki/Supernova">supernovae</a> &#8212; energetic explosions that typically mark the death throes of massive stars. Elements heavier than oxygen are disseminated mostly through supernovae, and elements heavier than iron come <em>almost only</em> from supernovae. This means that <em>literally everything around you</em> is full of atoms that were originally created in massive stars that exploded and sent those elements flying into interstellar space, where they eventually coalesced into dust and became you and the Earth you&#8217;re standing on.</p>
<p>Being a big fan of <a href="http://biphenyl.org/blog/2008/01/01/citation-needed/">stickers</a> you can <a href="http://biphenyl.org/blog/2008/10/16/accuracy-in-labeling-property-of-the-bavarian-illuminati/">put anywhere</a>, I thought a sticker campaign would be the perfect cheeky way to engage in some informal education! I modeled them after the <a href="http://www.flickr.com/photos/admurder/317971487/">labels warning of cancer risk</a> that you find on household chemicals, furniture, and almost every building in the state of California. They&#8217;re both factually correct, but while knowing that everything causes cancer is a buzzkill, knowing that everything came from supernovae is <em>awesome</em>.</p>
<p><a href="http://www.flickr.com/photos/mmechtley/4456862764/" title="Almost all elements around us on Earth originated in supernovae! So cool! by mmechtley, on Flickr"><img src="http://farm5.static.flickr.com/4068/4456862764_caa80b6ccf.jpg" width="500" height="333" alt="Almost all elements around us on Earth originated in supernovae! So cool!" /></a></p>
<p>The image I chose is one of my favorite Hubble Space Telescope pictures, the <a href="http://hubblesite.org/newscenter/archive/releases/2006/46/">Antennae Galaxies</a>. I&#8217;ve photoshopped the fake supernovae over the top. As always, there&#8217;s a <a href="http://www.flickr.com/photos/mmechtley/sets/72157623551813735/">Flickr set</a> that will continue growing. Here are the source files so you can print some yourself &#8212; they&#8217;re intended for 2.5&#8243; x 2.5&#8243; sticker backs.<br />
<a href="http://dl.dropbox.com/u/209408/blog/supernovae.psd">Master psd</a><br />
<a href="http://www.dafont.com/ubahn.font">UBahn font</a><br />
<a href="http://www.dafont.com/patagonian-titles.font">Patagonian font (with bonus dinosaurs!)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://biphenyl.org/blog/2010/03/23/accuracy-in-labeling-supernovae/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

