Difference between revisions of "Shading Technique - Glow Mapping"
From Horde3D Wiki
(draft) |
m (fixed a typo) |
||
(2 intermediate revisions by the same user not shown) | |||
Line 7: | Line 7: | ||
== Overview == | == Overview == | ||
For an in-depth overview of this technique, see the Gamasutra article [http://www.gamasutra.com/features/20040526/james_pfv.htm Real-Time Glow] by By Greg James and John O’Rorke. | For an in-depth overview of this technique, see the Gamasutra article [http://www.gamasutra.com/features/20040526/james_pfv.htm 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''' | ||
+ | |||
+ | {{CppSourceCode| | ||
+ | description= Setup the RenderTargets. If this is for HDR, then these RenderTargets will already exist, so just change depthBuf to "true" on the first one| | ||
+ | code= | ||
+ | <source lang="cpp" line="1"> | ||
+ | <Setup> | ||
+ | <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" /> | ||
+ | </Setup> | ||
+ | </source>}} | ||
+ | |||
+ | |||
+ | {{CppSourceCode| | ||
+ | description= insert this new stage after the "Geometry" stage.| | ||
+ | code= | ||
+ | <source lang="cpp" line="1"> | ||
+ | <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> | ||
+ | </source>}} | ||
+ | |||
+ | |||
+ | '''New shader code''' | ||
+ | |||
+ | {{CppSourceCode| | ||
+ | description= This context is designed to be added to a copy of the parallax shader - parallax_glow.shader.xml| | ||
+ | code= | ||
+ | <source lang="cpp" line="1"> | ||
+ | <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> | ||
+ | </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>}} | ||
+ | |||
+ | |||
+ | |||
+ | {{CppSourceCode| | ||
+ | description= This context is designed to be added to the original skinning shaders - skinning.shader.xml and skinning_metal.shader.xml| | ||
+ | code= | ||
+ | <source lang="cpp" line="1"> | ||
+ | <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> | ||
+ | </source>}} | ||
+ | |||
== Example Result == | == Example Result == |
Latest revision as of 01:15, 8 August 2008
|
|