diff --git a/Effects/bumpspec.eff b/Effects/bumpspec.eff new file mode 100644 index 000000000..1fa9fd0c9 --- /dev/null +++ b/Effects/bumpspec.eff @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Bump and specular effect +parameters : + texture[0] -> colormap + texture[2] -> normal map + specularity in alpha channel + +eg : +in model.xml : + <effect> + <inherits-from>Aircraft/A320/Models/Effects/bumpspec</inherits-from> + <object-name>Fuselage</object-name> + </effect> + +in Aircraft/A320/Models/Effects/a320_bumpspec.eff ( or whatever, private to the model ) + +<PropertyList> + <name>Aircraft/A320/Models/Effects/a320_bumpspec</name> + <inherits-from>Effects/bumpspec</inherits-from> + <parameters> + <texture n="2"> + <image>Aircraft/A320/Models/Effects/textures/a320_normals.png</image> + <filter>linear-mipmap-linear</filter> + <wrap-s>repeat</wrap-s> + <wrap-t>repeat</wrap-t> + <internal-format>normalized</internal-format> + </texture> + </parameters> +</PropertyList> +--> +<PropertyList> + <name>Effects/bumpspec</name> + <inherits-from>Effects/model-default</inherits-from> + <generate> + <normal type="int">15</normal> + <tangent type="int">6</tangent> + <binormal type="int">7</binormal> + </generate> + <technique n="10"> + <predicate> + <and> + <property>/sim/rendering/shader-effects</property> + <or> + <less-equal> + <value type="float">2.0</value> + <glversion/> + </less-equal> + <and> + <extension-supported>GL_ARB_shader_objects</extension-supported> + <extension-supported>GL_ARB_shading_language_100</extension-supported> + <extension-supported>GL_ARB_vertex_shader</extension-supported> + <extension-supported>GL_ARB_fragment_shader</extension-supported> + </and> + </or> + </and> + </predicate> + <pass> + <texture-unit> + <unit>0</unit> + <image><use>texture[0]/image</use></image> + <filter><use>texture[0]/filter</use></filter> + <wrap-s><use>texture[0]/wrap-s</use></wrap-s> + <wrap-t><use>texture[0]/wrap-t</use></wrap-t> + <internal-format><use>texture[1]/internal-format</use></internal-format> + </texture-unit> + <texture-unit> + <unit>1</unit> + <image><use>texture[2]/image</use></image> + <filter><use>texture[2]/filter</use></filter> + <wrap-s><use>texture[2]/wrap-s</use></wrap-s> + <wrap-t><use>texture[2]/wrap-t</use></wrap-t> + <internal-format><use>texture[2]/internal-format</use></internal-format> + </texture-unit> + <program> + <vertex-shader n="0">Shaders/bumpspec.vert</vertex-shader> + <fragment-shader n="0">Shaders/bumpspec.frag</fragment-shader> + <uniform> + <name>tex_color</name> + <type>sampler-2d</type> + <value type="int">0</value> + </uniform> + <uniform> + <name>tex_normal</name> + <type>sampler-2d</type> + <value type="int">1</value> + </uniform> + <uniform> + <name>tex_specular</name> + <type>sampler-2d</type> + <value type="int">2</value> + </uniform> + </program> + <uniform> + <name>tex_color</name> + <type>sampler-2d</type> + <value type="int">0</value> + </uniform> + <uniform> + <name>tex_normal</name> + <type>sampler-2d</type> + <value type="int">1</value> + </uniform> + </pass> + </technique> +</PropertyList> diff --git a/Shaders/bumpspec.frag b/Shaders/bumpspec.frag new file mode 100644 index 000000000..49ec8188e --- /dev/null +++ b/Shaders/bumpspec.frag @@ -0,0 +1,53 @@ +// -*- mode: C; -*- +// Licence: GPL v2 +// Authors: Original code by Thorsten Jordan, Luis Barrancos and others (dangerdeep.sf.net) +// Modified by Emilian Huminiuc (emilianh@gmail.com) (i4dnf on the flightgear forums). +// fixme: maybe lookup texmap is faster than pow(). Quick tests showed that this is not the case... + +uniform sampler2D tex_color; // (diffuse) color map, RGB +uniform sampler2D tex_normal; // normal map, RGB + A Specular + + +varying vec4 ecPosition; +varying vec3 lightdir, halfangle; + +void main() +{ + // get and normalize vector to light source + vec3 L = normalize(lightdir); + + // get and normalize normal vector from texmap + vec4 v = texture2D(tex_normal, gl_TexCoord[0].st); + vec3 N = normalize(vec3(v.xyz * 2.0 - 1.0)); + N.y = -N.y; + if (!gl_FrontFacing) + N = -N; + + // compute specular color + // get and normalize half angle vector + vec3 H = normalize(halfangle); + + // compute resulting specular color + vec3 specular_color = vec3(gl_FrontMaterial.specular) * + pow(max(dot(H, N), 0.0), gl_FrontMaterial.shininess); + + // compute diffuse color + vec3 diffuse_color = vec3(texture2D(tex_color, gl_TexCoord[0].st)); + + // handle ambient + diffuse_color = diffuse_color * mix(max(dot(L, N), 0.0), 0.6, gl_LightSource[0].ambient.r); + + specular_color = specular_color * v.a; + + // final color of fragment + vec3 final_color = clamp((diffuse_color + specular_color) * vec3(gl_LightSource[0].diffuse /*light_color*/), 0.0, 1.0); + + float fog_factor; + float fogCoord = ecPosition.z; + const float LOG2 = 1.442695; + fog_factor = exp2(-gl_Fog.density * gl_Fog.density * fogCoord * fogCoord * LOG2); + fog_factor = clamp(fog_factor, 0.0, 1.0); + + // output color is a mix between fog and final color + gl_FragColor = vec4(mix(vec3(gl_Fog.color), final_color, fog_factor), 1.0); +} diff --git a/Shaders/bumpspec.vert b/Shaders/bumpspec.vert new file mode 100644 index 000000000..9b49dcce6 --- /dev/null +++ b/Shaders/bumpspec.vert @@ -0,0 +1,53 @@ +// -*- mode: C; -*- +// Licence: GPL v2 +// Authors: Original code by Thorsten Jordan, Luis Barrancos and others (dangerdeep.sf.net) +// Modified by Emilian Huminiuc (emilianh@gmail.com) (i4dnf on the flightgear forums). + +/* input: +gl_Vertex +gl_Normal (tangentz) +gl_MultiTexCoord0 (texcoord) +tangentx_righthanded (tangentx,righthanded-factor) +*/ + +/* can we give names to default attributes? or do we need to use named attributes for that? +how to give named attributes with vertex buffer objects? +we could assign them to a variable, but would that be efficient? an unnecessary copy. +but the shader compiler should be able to optimize that... +the way should be to use vertex attributes (together with vertex arrays or VBOs), +that have a name and use that name here. +until then, access sources directly or via a special variable. +*/ + +varying vec4 ecPosition; +varying vec3 lightdir, halfangle; +attribute vec4 tangent, binormal; + +void main() +{ + ecPosition = gl_ModelViewMatrix * gl_Vertex; + + // compute direction to light in object space (L) + vec3 lightpos_obj = vec3(gl_ModelViewMatrixInverse * gl_LightSource[0].position); + vec3 lightdir_obj = normalize(lightpos_obj); + + // direction to viewer (E) + // compute direction to viewer (E) in object space (mvinv*(0,0,0,1) - inputpos) + vec3 viewerdir_obj = normalize(vec3(gl_ModelViewMatrixInverse[3]) - vec3(gl_Vertex)); + + // compute halfangle vector (H = ||L+E||) + vec3 halfangle_obj = normalize(viewerdir_obj + lightdir_obj); + + // transform light direction to tangent space + lightdir.x = dot(tangent, lightdir_obj); + lightdir.y = dot(binormal, lightdir_obj); + lightdir.z = dot(gl_Normal, lightdir_obj); + + halfangle.x = dot(tangent, halfangle_obj); + halfangle.y = dot(binormal, halfangle_obj); + halfangle.z = dot(gl_Normal, halfangle_obj); + + // finally compute position + gl_Position = ftransform(); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; +}