PDA

View Full Version : attenuation-independent light intensity



Vexator
08-07-2006, 05:50 AM
my simple phong shader simulates a point light source with linear attenuation. this way i can have bright, intense lights when i set a large radius.. but if i want them to have a small radius, they faint.

so my question is - how can i simulate a (point) light source that can have a small radius, but that's still intense? in other words, how can i make the intensity of the light source independent from the light's radius and the consequential attenuation?

thanks :)

ZbuffeR
08-07-2006, 06:38 AM
Use more than 1.0 as brightness value.

And you may use 2 radii : a Near, and a Far

Light is not attenuated until Near, then linear falloff until Far.
That way you have better control on the near scale.

Vexator
08-08-2006, 05:48 AM
Use more than 1.0 as brightness value.ok so i'm dong it like this now:

vertex program:

And you may use 2 radii : a Near, and a Farthat's an interesting idea, do you have any implementation samples?

thank you!

Vexator
09-03-2006, 09:53 AM
ok here is my final shader - i still have two issuses, though:

- the shader still seems to illuminate geometry that's barely outside the light radius, i.e. the actual light radius is a big bigger than it should be. that sucks, as i'd like to cull this geometry.
- in some cases, specular highlights appear in reverse color when the geometry is almost back-facing the light source.

any idea what's wrong? and do you see other bugs/things that could be improved (besides the if-conditions and the extra texture lookup for highlights)? thanks! :)

vertex:


varying vec2 v_Coordinates;
varying vec3 v_ViewDirection;
varying vec3 v_LightDirection;

attribute vec3 a_Normal;
attribute vec3 a_Tangent;
attribute vec3 a_Bitangent;
attribute vec2 a_Coordinates;

uniform float u_LightRadius;
uniform vec3 u_LightPosition;
uniform vec3 u_CameraPosition;

void main()
{
v_Coordinates = a_Coordinates;
vec3 Vertex = vec3(gl_ModelViewMatrix*gl_Vertex);

vec3 ViewDirection = u_CameraPosition-Vertex;
vec3 LightDirection = (1.0/u_LightRadius)*(u_LightPosition-Vertex);

vec3 Normal = gl_NormalMatrix*a_Normal;
vec3 Tangent = gl_NormalMatrix*a_Tangent;
vec3 Bitangent = gl_NormalMatrix*a_Bitangent;

v_ViewDirection.x = dot( Tangent, ViewDirection );
v_ViewDirection.y = dot( Bitangent, ViewDirection );
v_ViewDirection.z = dot( Normal, ViewDirection );

v_LightDirection.x = dot( Tangent, LightDirection.xyz );
v_LightDirection.y = dot(Bitangent, LightDirection.xyz );
v_LightDirection.z = dot( Normal, LightDirection.xyz );

gl_Position = ftransform();
}fragment:


varying vec2 v_Coordinates;
varying vec3 v_ViewDirection;
varying vec3 v_LightDirection;

uniform float u_Factor;

uniform float u_LightIntensity;
uniform vec3 u_LightDiffuseColor;
uniform vec3 u_LightSpecularColor;

uniform bool u_UseTexture0;
uniform bool u_UseTexture1;

uniform sampler2D u_Texture0;
uniform sampler2D u_Texture1;

uniform float u_MaterialShininess;
uniform bool u_UseSpecularHighlights;

void main()
{
// compute attenuation
float Attenuation = clamp( 1.0-dot(v_LightDirection, v_LightDirection), 0.0, 1.0 );

// normalize direction vectors
vec3 ViewDirection = normalize( v_ViewDirection );
vec3 LightDirection = normalize( v_LightDirection );

// set defaults
vec3 Normal = vec3( 0.0, 0.0, 1.0 );
vec3 BaseColor = vec3( 1.0, 1.0, 1.0 );

// diffuse map
if( u_UseTexture0 )
BaseColor = texture2D( u_Texture0, v_Coordinates ).xyz;

// normal map
if( u_UseTexture1 )
Normal = normalize( (texture2D(u_Texture1, v_Coordinates).xyz*2.0)-1.0 );

// compute dot product
float NdotL = dot( Normal, LightDirection );

// compute final color
vec3 FinalColor = ( BaseColor*u_LightDiffuseColor*NdotL*u_LightIntensi ty )*Attenuation;

// compute highlights
if( u_UseSpecularHighlights )
{
vec3 Reflection = reflect( -LightDirection, Normal );
float Specular = pow( max(dot(Reflection, ViewDirection), 0.0), u_MaterialShininess );

FinalColor += ( u_LightSpecularColor*Specular*u_LightIntensity )*Attenuation;
}

// output color
gl_FragColor = vec4( FinalColor, 1.0 );
}