🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

How do I implement soft fall off boundary for calculating point only inside sphere with fixed radius?

Started by
4 comments, last by _WeirdCat_ 3 years ago

I am trying to prevent this problem in opengl:

as you can see there is hard fall of in light if a fragment is too far away from light.

this was when the light sphere radius was 11

I then mildly solved this problem and now its like this:

this was done with this code:

for (int i = 0; i < activePointLights; i++) {            
            float dist=distance(f_position,pointLights[i].position);         
            if (dist <= pointLights[i].radius+pointLights[i].dropoffRadius){
                result += CalcPointLight(pointLights[i], norm, f_position, viewDir, diffColor, tangentLightPos, tangentFragPos)*clamp(2*pointLights[i].dropoffRadius*(1-dist)+pointLights[i].radius-pointLights[i].dropoffRadius,0,1);                
            }
        }

here dropoffradius was 1 and the light sphere radius was 23

the equation inside clamp was made by linearly interpolating input from (sphereradius - dropoffradius to sphereradius + dropoffradius) being mapped to range (1 to 0).

When I increase pointLights[i].dropoffRadius to 2 I get way less illuminated area and I have to crank up the radius of the pointlight sphere.

what I want now is to make the edges of the boundary of light affecting fragments in plane of above picture more soft controlled by a value like pointLights[i].dropoffRadius.

Advertisement

Found some useful formulas here: https://geom.io/bakery/wiki/index.php?title=Point_Light_Attenuation

Edit: Also here see under ‘point lights’: https://learnopengl.com/Lighting/Light-casters​​

ankit7 said:
and I have to crank up the radius of the pointlight sphere.

The more correct you want it to look, to more you have to ‘crank up’. No way around that.

Physical inverse square falloff is usually not practical, so it's about choosing a hack which suits your needs best.

Post above is true to some extent, you need to make your own quadratic light values and choose which fits your need rest is finding the distance light will be invisible which will be your already defined radius meaning

For a start pick: constant 0.85

Linear 1.0

Quadratic 0.06


//If we want attenuation to match light radius we first need to define at which attenuation light becomes invisible
//lets assume at 0.004 (rounded 1.0 / 256.0)
float Attenuation(float dstx)
{
return 1.0 / (LConst + LLinear * dstx + LQuadratic * (dstx * dstx));
}

float CalcLightAttenuation(float REALradius)
{
float fdst = n3ddistance(LPos, vertex_pos);
float kompot = fdst / LRadius;
//float intensity = clampme(1.0 - kompot);
return Attenuation(REALradius * kompot);
}

now call CalcLightAttenuation(your radius);
FinalColor 

tcol is rgba value of the texture



vec3 ambient = lightColor * MAmb * (intensity*attenuation);

	vec3 diffuse = lightColor * MDiff * (intensity*attenuation);
	float lspec = Specular();
	vec3 specular = lightColor * (lspec * MSpec);



		color = vec4((ambient+diffuse+specular)*tcol.rgb, tcol.a);

Thanks for all of your answers and resources. I ended up solving that by following:

 for (int i = 0; i < activePointLights; i++) {            
     float dist=distance(f_position,pointLights[i].position);     
     float int_by_at =pointLights[i].intensity/ (pointLights[i].constant + pointLights[i].linear * dist + pointLights[i].quadratic * (dist * dist));    
     if (int_by_at > 0.004){              
         result += CalcPointLight(pointLights[i], norm, f_position, viewDir, diffColor, tangentLightPos, tangentFragPos, int_by_at);
     }
 }

I am sorry i didnt provide full code now it has everything you need LRadius ia the light radius

uniform vec3 LPos;
uniform vec3 LDiff;
uniform vec3 LAmb;
uniform vec3 LSpec;
uniform float LRadius;
uniform float LConst;
uniform float LLinear;
uniform float LQuadratic;
uniform int DirectionalLight;
uniform vec3 LDirection;
uniform float z_far;

uniform vec3 MAmb;
uniform vec3 MDiff;
uniform vec3 MSpec;
uniform float MShininess;


//If we want attenuation to match light radius we first need to define at which attenuation light becomes invisible
//lets assume at 0.004 (rounded 1.0 / 256.0)
float Attenuation(float dstx)
{
return 1.0 / (LConst + LLinear * dstx + LQuadratic * (dstx * dstx));
}


float CalcLightAttenuation(float REALradius)
{
	float fdst = n3ddistance(LPos, vertex_pos);
	float kompot = fdst / LRadius;
	//float intensity = clampme(1.0 - kompot);
	return Attenuation(REALradius * kompot);
}





	vec3 light_vert = normalize( vectorAB( LPos, vertex_pos ) );
	float intensity = max(-dot(light_vert, normal), 0.0);


	vec3 lightColor = LAmb + LDiff;
	float lightMax  = max(max(lightColor.x, lightColor.y), lightColor.z);
	float REALradius = (-LLinear +  sqrt(LLinear * LLinear - 4.0 * LQuadratic * (LConst - (256.0 / 5.0) * lightMax))) / (2.0 * LQuadratic);
	float attenuation = CalcLightAttenuation(REALradius);

vec4 tcol = texture2D(face_tex, texcoord);

	vec3 ambient = lightColor * MAmb * (intensity*attenuation);

	vec3 diffuse = lightColor * MDiff * (intensity*attenuation);
	float lspec = Specular();
	vec3 specular = lightColor * (lspec * MSpec);

Final_color = vec4((ambient+diffuse+specular)*tcol.rgb, tcol.a);

This topic is closed to new replies.

Advertisement