Attenuation-independent light intensity

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 :slight_smile:

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.

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 Far
that’s an interesting idea, do you have any implementation samples?

thank you!

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! :slight_smile:


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, );
	v_LightDirection.y = dot(Bitangent, );
	v_LightDirection.z = dot( Normal, );

	gl_Position = ftransform();


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_LightIntensity )*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 );

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.