Shading Technique - Glow Mapping

From Horde3D Wiki
Revision as of 10:09, 7 August 2008 by Darkangel (talk | contribs) (added a dump of my code until I actually finish writing this)
Jump to: navigation, search

I'm in the process of writing this article - come back later!

Overview

For an in-depth overview of this technique, see the Gamasutra article Real-Time Glow by By Greg James and John O’Rorke.

Temporary code dump

Until I finish writing this article, here's the undocumented code ;)

Pipeline changes

Setup the RenderTargets. If this is for HDR, then these RenderTargets will already exist, so just change depthBuf to "true" on the first one
<stage id="Glow">
	<RenderTarget id="BLURBUF1" depthBuf="true"  numColBufs="1" format="RGBA8" bilinear="true" scale="0.25" />
	<RenderTarget id="BLURBUF2" depthBuf="false" numColBufs="1" format="RGBA8" bilinear="true" scale="0.25" />
</stage>


insert this new stage after the "Geometry" stage.
<stage id="Glow">
	<SwitchTarget target="BLURBUF1" />			
	<ClearTarget depthBuf="true" colBuf0="true" />
	<DrawGeometry context="GLOWMASK" />
	
	<!-- Repeat these steps as many times as you like, it makes the bloom softer -->
	<SwitchTarget target="BLURBUF2" />
	<BindBuffer texUnit="0" target="BLURBUF1" bufIndex="0" />
	<DrawQuad   material="postGlow.material.xml" context="BLURV" />
	<SwitchTarget target="BLURBUF1" />
	<BindBuffer texUnit="0" target="BLURBUF2" bufIndex="0" />
	<DrawQuad   material="postGlow.material.xml" context="BLURH" />
	
	<SwitchTarget target="BLURBUF2" />
	<BindBuffer texUnit="0" target="BLURBUF1" bufIndex="0" />
	<DrawQuad   material="postGlow.material.xml" context="BLURV" />
	<SwitchTarget target="BLURBUF1" />
	<BindBuffer texUnit="0" target="BLURBUF2" bufIndex="0" />
	<DrawQuad   material="postGlow.material.xml" context="BLURH" />
	
	<SwitchTarget target="BLURBUF2" />
	<BindBuffer texUnit="0" target="BLURBUF1" bufIndex="0" />
	<DrawQuad   material="postGlow.material.xml" context="BLURV" />
	<SwitchTarget target="BLURBUF1" />
	<BindBuffer texUnit="0" target="BLURBUF2" bufIndex="0" />
	<DrawQuad   material="postGlow.material.xml" context="BLURH" />
	
	<!-- In the HDR version, target should be set to "HDRBUF" -->
	<SwitchTarget target="" />
	<BindBuffer texUnit="0" target="BLURBUF1" bufIndex="0" />
	<DrawQuad material="postGlow.material.xml" context="FINALPASS" />
</stage>


New shader code

This context is designed to be added to a copy of the parallax shader - parallax_glow.shader.xml
<Context id="GLOWMASK">	
	<!-- This material does glow - output colors masked by the alpha channel -->
	<VertexShader>
		<InsCode code="utilityLib/vertCommon.glsl" />
		<DefCode>
		<![CDATA[
			uniform vec3 viewer;
			attribute vec2 texCoords0;
			attribute vec3 normal, tangent, bitangent;
			varying vec3 eyeTS;
			varying vec2 texCoords;
			varying vec4 pos;
		
			void main( void )
			{
				// Transform tangent space basis
				vec3 tsbTangent = normalize( calcWorldVec( tangent ) );
				vec3 tsbBitangent = normalize( calcWorldVec( bitangent ) );
				vec3 tsbNormal = normalize( calcWorldVec( normal ) );
				
				// Calculate world space position
				pos = calcWorldPos( gl_Vertex );
				
				// Eye vector and eye vector in tangent space
				eyeTS = calcTanVec( viewer - pos.xyz, tsbTangent, tsbBitangent, tsbNormal );
		
				// Calculate texture coordinates and clip space position
				texCoords = texCoords0;
				gl_Position = gl_ModelViewProjectionMatrix * pos;
			}
		]]>
		</DefCode>
	</VertexShader>
	
	<FragmentShader>
		<DefCode>
		<![CDATA[
			uniform sampler2D tex0;
			varying vec3 eyeTS;
			varying vec2 texCoords;
			
			void main( void )
			{
				const float plxScale = 0.03;
				const float plxBias = -0.015;
				
				// Iterative parallax mapping
				vec3 newCoords = vec3( texCoords, 0 );
				vec3 eye = normalize( eyeTS );
				for( int i = 0; i < 4; ++i )
				{
					vec4 nmap = texture2D( tex0, texCoords.st );
					float height = nmap.a * plxScale + plxBias;
					newCoords += (height - newCoords.p) * nmap.z * eye;
				}
				
				vec4 glow = texture2D( tex0, newCoords.st ).rgba;
				glow *= glow.a;
				
				gl_FragColor = glow;
			}
		]]>
		</DefCode>
	</FragmentShader>
</Context>


This context is designed to be added to the original skinning shaders - skinning.shader.xml and skinning_metal.shader.xml
<Context id="GLOWMASK">	
	<!-- This material does not glow - output black pixels -->
	<VertexShader>
		<InsCode code="utilityLib/vertCommon.glsl" />
		<InsCode code="utilityLib/vertSkinning.glsl" />
		<DefCode>
		<![CDATA[
			void main( void )
			{
				// Calculate skinning matrices
				mat4 skinningMat = calcSkinningMat();
				mat3 skinningMatVec = getSkinningMatVec( skinningMat );
				// Calculate world space position
				vec4 pos = calcWorldPos( skinPos( gl_Vertex, skinningMat ) );
				// Calculate clip space position
				gl_Position = gl_ModelViewProjectionMatrix * pos;
			}
		]]>
		</DefCode>
	</VertexShader>
	
	<FragmentShader>
		<InsCode code="utilityLib/fragLighting.glsl" />
		<DefCode>
		<![CDATA[
			void main( void )
			{
				gl_FragColor.rgb = vec3(0,0,0);
			}
		]]>
		</DefCode>
	</FragmentShader>
</Context>


Example Result

Click here to view

To-Do List for this Article

- Write the article, describe the code and pipeline changes required
- Add pictures
- Ask for permission to upload a ZIP of my finished xml/tga files ;)

Technique - Glow
File:Todo.jpg
Using an alpha channel to add emissive bloom.
Version: 1.0
Compatible with Horde3D: 1.0 beta
Release date: 2008-08-06
Author(s): DarkAngel