|
|
Line 135: |
Line 135: |
| </Context> | | </Context> |
| </source>}} | | </source>}} |
| + | |
| + | |
| + | |
| + | {{CppSourceCode| |
| + | description= This is a new shader, called postGlow.shader.xml| |
| + | code= |
| + | <source lang="cpp" line="1"> |
| + | <Shader> |
| + | |
| + | <Context id="BLURH"> |
| + | <RenderConfig writeDepth="false" /> |
| + | <VertexShader> |
| + | <DefCode> |
| + | <![CDATA[ |
| + | varying vec2 texCoord; |
| + | void main( void ) |
| + | { |
| + | texCoord = gl_MultiTexCoord0.st; |
| + | gl_Position = gl_ProjectionMatrix * gl_Vertex; |
| + | } |
| + | ]]> |
| + | </DefCode> |
| + | </VertexShader> |
| + | <FragmentShader> |
| + | <InsCode code="utilityLib/fragPostProcess.glsl" /> |
| + | <DefCode> |
| + | <![CDATA[ |
| + | uniform sampler2D tex; |
| + | uniform vec2 frameBufSize; |
| + | varying vec2 texCoord; |
| + | void main( void ) |
| + | { |
| + | float halfPixel = 0.5 / frameBufSize.x; |
| + | vec4 col = texture2D( tex, texCoord + vec2( halfPixel, 0.0 ) ); |
| + | col += texture2D( tex, texCoord - vec2( halfPixel, 0.0 ) ); |
| + | col += texture2D( tex, texCoord + vec2( halfPixel*3.0, 0.0 ) ); |
| + | col += texture2D( tex, texCoord - vec2( halfPixel*3.0, 0.0 ) ); |
| + | gl_FragColor = col * 0.25; |
| + | } |
| + | ]]> |
| + | </DefCode> |
| + | </FragmentShader> |
| + | </Context> |
| + | <Context id="BLURV"> |
| + | <RenderConfig writeDepth="false" /> |
| + | <VertexShader> |
| + | <DefCode> |
| + | <![CDATA[ |
| + | varying vec2 texCoord; |
| + | void main( void ) |
| + | { |
| + | texCoord = gl_MultiTexCoord0.st; |
| + | gl_Position = gl_ProjectionMatrix * gl_Vertex; |
| + | } |
| + | ]]> |
| + | </DefCode> |
| + | </VertexShader> |
| + | <FragmentShader> |
| + | <InsCode code="utilityLib/fragPostProcess.glsl" /> |
| + | <DefCode> |
| + | <![CDATA[ |
| + | uniform sampler2D tex; |
| + | uniform vec2 frameBufSize; |
| + | varying vec2 texCoord; |
| + | void main( void ) |
| + | { |
| + | float halfPixel = 0.5 / frameBufSize.y; |
| + | vec4 col = texture2D( tex, texCoord + vec2( 0.0, halfPixel ) ); |
| + | col += texture2D( tex, texCoord - vec2( 0.0, halfPixel ) ); |
| + | col += texture2D( tex, texCoord + vec2( 0.0, halfPixel*3.0 ) ); |
| + | col += texture2D( tex, texCoord - vec2( 0.0, halfPixel*3.0 ) ); |
| + | gl_FragColor = col * 0.25; |
| + | } |
| + | ]]> |
| + | </DefCode> |
| + | </FragmentShader> |
| + | </Context> |
| + | |
| + | <Context id="FINALPASS"> |
| + | <RenderConfig writeDepth="false" blendMode="ADD" /> |
| + | |
| + | <VertexShader> |
| + | <DefCode> |
| + | <![CDATA[ |
| + | varying vec2 texCoord; |
| + | |
| + | void main( void ) |
| + | { |
| + | texCoord = gl_MultiTexCoord0.st; |
| + | gl_Position = gl_ProjectionMatrix * gl_Vertex; |
| + | } |
| + | ]]> |
| + | </DefCode> |
| + | </VertexShader> |
| + | |
| + | <FragmentShader> |
| + | <DefCode> |
| + | <![CDATA[ |
| + | uniform sampler2D tex0, tex1; |
| + | uniform vec2 frameBufSize; |
| + | uniform vec4 hdrParams; |
| + | varying vec2 texCoord; |
| + | |
| + | void main( void ) |
| + | { |
| + | gl_FragColor = texture2D( tex0, texCoord ); // Glow color |
| + | } |
| + | ]]> |
| + | </DefCode> |
| + | </FragmentShader> |
| + | </Context> |
| + | </Shader> |
| + | </source>}} |
| + | |
| + | |
| + | {{CppSourceCode| |
| + | description= The material to go with the postGlow shader - postGlow.material.xml| |
| + | code= |
| + | <source lang="cpp" line="1"> |
| + | <Material> |
| + | <Shader source="postGlow.shader.xml"/> |
| + | </Material> |
| + | </source>}} |
| + | |
| | | |
| | | |
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 is a new shader, called postGlow.shader.xml |
<Shader>
<Context id="BLURH">
<RenderConfig writeDepth="false" />
<VertexShader>
<DefCode>
<![CDATA[
varying vec2 texCoord;
void main( void )
{
texCoord = gl_MultiTexCoord0.st;
gl_Position = gl_ProjectionMatrix * gl_Vertex;
}
]]>
</DefCode>
</VertexShader>
<FragmentShader>
<InsCode code="utilityLib/fragPostProcess.glsl" />
<DefCode>
<![CDATA[
uniform sampler2D tex;
uniform vec2 frameBufSize;
varying vec2 texCoord;
void main( void )
{
float halfPixel = 0.5 / frameBufSize.x;
vec4 col = texture2D( tex, texCoord + vec2( halfPixel, 0.0 ) );
col += texture2D( tex, texCoord - vec2( halfPixel, 0.0 ) );
col += texture2D( tex, texCoord + vec2( halfPixel*3.0, 0.0 ) );
col += texture2D( tex, texCoord - vec2( halfPixel*3.0, 0.0 ) );
gl_FragColor = col * 0.25;
}
]]>
</DefCode>
</FragmentShader>
</Context>
<Context id="BLURV">
<RenderConfig writeDepth="false" />
<VertexShader>
<DefCode>
<![CDATA[
varying vec2 texCoord;
void main( void )
{
texCoord = gl_MultiTexCoord0.st;
gl_Position = gl_ProjectionMatrix * gl_Vertex;
}
]]>
</DefCode>
</VertexShader>
<FragmentShader>
<InsCode code="utilityLib/fragPostProcess.glsl" />
<DefCode>
<![CDATA[
uniform sampler2D tex;
uniform vec2 frameBufSize;
varying vec2 texCoord;
void main( void )
{
float halfPixel = 0.5 / frameBufSize.y;
vec4 col = texture2D( tex, texCoord + vec2( 0.0, halfPixel ) );
col += texture2D( tex, texCoord - vec2( 0.0, halfPixel ) );
col += texture2D( tex, texCoord + vec2( 0.0, halfPixel*3.0 ) );
col += texture2D( tex, texCoord - vec2( 0.0, halfPixel*3.0 ) );
gl_FragColor = col * 0.25;
}
]]>
</DefCode>
</FragmentShader>
</Context>
<Context id="FINALPASS">
<RenderConfig writeDepth="false" blendMode="ADD" />
<VertexShader>
<DefCode>
<![CDATA[
varying vec2 texCoord;
void main( void )
{
texCoord = gl_MultiTexCoord0.st;
gl_Position = gl_ProjectionMatrix * gl_Vertex;
}
]]>
</DefCode>
</VertexShader>
<FragmentShader>
<DefCode>
<![CDATA[
uniform sampler2D tex0, tex1;
uniform vec2 frameBufSize;
uniform vec4 hdrParams;
varying vec2 texCoord;
void main( void )
{
gl_FragColor = texture2D( tex0, texCoord ); // Glow color
}
]]>
</DefCode>
</FragmentShader>
</Context>
</Shader>
|
The material to go with the postGlow shader - postGlow.material.xml |
<Material>
<Shader source="postGlow.shader.xml"/>
</Material>
|
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 |
|