lighting...

I’m trying to put together a Vertex and fragment shader that just do what the 1.5 pipeline does.

I can’t seem to get the same performance out of my vertex shader when computing lighting as OpenGL (I’m using a straight copy out of the orange book for my lighting calculations).

I’m on a 5950.

has anyone implemented lighting (with multiple lights) and gotten basically the same performance as OpenGL fixed?

any ideas how to optimize and what built in uniform varibles I should make use of?

I don’t really have a solution to your problem. All I can say is despite all my efforts, terrible performances on me 5900 when I use a fragment shader or a fragment program, even if it’s a simple one. :frowning:

The Radeon is much better for the shaders. I can’t wait to see how the GeForce 6800 will be.

You won’t for now get the same performance as the FFP. And besides this, most modern cards nonetheless don’t have a FFP anymore but emulate it via shaders.

But you need to remember that all glslang-implementations out there are still in beta-stage, and in that stage it’s bug-finding before speed-optimization. I for myself have made a simple bump-mapping scenario where I do the bump via an ARB-shader and a glslang-shader, and the ARB-shader (although doing nothing more or less) is faster by a good amount. But as the glslang-implementations mature, the speed will get faster and hopefully get as fast as ARB-shaders (at least on current hw. My 9700 is significant slower on glslang than on a similar ARB-shader).

vince, I’ve had the chance to run my shader on an NV40 and I can tell you that it ran just about in real time. the NV40 is some serious $hit!

Aeluned, you lucky bastard! I wanna try one of those cards too. Do you know when they are supposed to release them?

I can only speculate…and don’t quote me on this, but I think they may become widely available sometime in July.

What’s the point in using a shader if you want it to do exactly the same thing as the fixed-function pipeline?

– Tom

I think the GeForceFX has some fixed function vertex processing hardware in addition to the vertex shaders. The reason is (I’m guessing) to get good performance in professional CAD like apps which often are very geometry limited.

Besides, even if there wasn’t any fixed function vertex processing hardware, if you’re using fixed function the drivers can used special hand tuned assembly shaders done specially for each hardware model for optimal performance. I doubt nvidias shadre compiler beats nvidias driver engineers.

Tom -
unless I’m missing something, If I write a vertex shader and I want lighting I’m going to have to implement it. I’m not trying to recreate the whole FFP, but I do need to recreate that part of it.

Okay, but that’s different from what you originally said :slight_smile:

As harsman already stated, the fixed-function stuff may run on dedicated hardware, whereas your shader has to go through the more general programmable pipeline. It seems perfectly reasonable to me that the added flexibility costs you some performance.

Just how big is the performance gap you’re trying to close?

– Tom

It’s severe. I’m getting hit with a rendering time 3x as long as using OpenGL FFP.

and this is only for vertex lighting.

my fragment program for bump mapping is useless. I get bored between frames :slight_smile: .

In case you or anyone wants to see what I’m doing here’s the vertex shader:

#pragma debug(on)

vec4 ecPosition;				//homogeneous eye coordinate vector.
vec3 ecPosition3;				//nonhomogeneous eye coordinate vector.
varying vec3 normal; 			//calculated vertex normal.
varying vec3 eye;				//eye vector.

struct TexInfo
{
	uniform sampler2D tex;		//texture unit
	int application;			//application(modulate,decal,interpolate,etc...)
	float transp;			//overall texture tranparency level
	int method;			//method(reflective,projected,etc...)
	int enabled;  			//is this texture unit enabled?
};
//max texture units exposed to application is currently 4.  There are some issues with iterating over an array inside a loop which is controlled
//by a uniform variable.  driver issues? not currently implemented? I have no idea at the moment.
uniform TexInfo textureInfo[4];

const int MAX_LIGHTS = 8; 			//restricted to 8 lights for now
uniform int lightEnabled[MAX_LIGHTS]; 	//is light n enabled?

//#########################################################################################         LIGHTING
//......------=========================================================------......
//		    Calculate light contribution from Directional Light i
//====================================================================
void DirectionalLight(in int i, in vec3 normal, inout vec4 ambient,inout vec4 diffuse, inout vec4 specular)
{
	float nDotVP; //normal . light direction
	float nDotHV; //normal . light half vector
	float pf;     //power factor

	nDotVP = max(0.0,dot(normal,vec3(gl_LightSource[i].position)));
	nDotHV = max(0.0,dot(normal,vec3(gl_LightSource[i].halfVector)));

	if(nDotVP == 0.0)
		pf = 0.0;
	else
		pf = pow(nDotHV,gl_FrontMaterial.shininess);

	ambient += gl_LightSource[i].ambient;
	diffuse += gl_LightSource[i].diffuse*nDotVP;
	specular += gl_LightSource[i].specular*pf;
}


//......------=========================================================------......
//			Calculate light contribution from Point Light i
//====================================================================
void PointLight(in int i,in vec3 normal,inout vec4 ambient,inout vec4 diffuse,inout vec4 specular)
{
	float nDotVP;			//normal . light direction
	float nDotHV;  			//normal . light half vector
	float pf;         		//power factor
	float attenuation;		//computed attenuation factor
	float d;			//distance from surface to light source
	vec3 VP;			//direction from surface to light position
	vec3 halfVector;		//direction of maximum highlights

	//compute distance between surface to light position
	VP = vec3 (gl_LightSource[i].position) - ecPosition3;

	//compute distance between surface and light position
	//d = length(VP);

	//normalize the vector from surface to light position
	VP = normalize(VP);
	
	//attenuation = 1.0 / (gl_LightSource[i].constantAttenuation + gl_LightSource[i].linearAttenuation * d + gl_LightSource[i].quadraticAttenuation * d * d);

	halfVector = normalize(VP + eye);

	nDotVP = max(0.0, dot(normal,VP));
	nDotHV = max(0.0, dot(normal,halfVector));

	if(nDotVP == 0.0)
		pf = 0.0;
	else
		pf = pow(nDotHV, gl_FrontMaterial.shininess);

	ambient += gl_LightSource[i].ambient;
	diffuse += gl_LightSource[i].diffuse  * nDotVP;// * attenuation;
	specular += gl_LightSource[i].specular * pf;// * attenuation;
}

//......------=========================================================------......
//			Calculate light contribution from Spot Light i
//====================================================================
void SpotLight(in int i,in vec3 normal,inout vec4 ambient,inout vec4 diffuse,inout vec4 specular)
{
	float nDotVP;	//normal . light direction
	float nDotHV;  	//normal . light half vector
	float pf;         	//power factor
	float spotDot;	//cosine of angle between spotlight
	float spotAttenuation;	//spotlight attenuation factor
	float attenuation;//computed attenuation factor
	float d;		//distance from surface to light source
	vec3 VP;	//direction from surface to light position
	vec3 halfVector;	//direction of maximum highlights

	//compute distance between surface to light position
	VP = vec3 (gl_LightSource[i].position) - ecPosition3;

	//compute distance between surface and light position
	d = length(VP);

	//normalize the vector from surface to light position
	VP = normalize(VP);
	
	attenuation = 1.0 / (gl_LightSource[i].constantAttenuation + gl_LightSource[i].linearAttenuation * d + gl_LightSource[i].quadraticAttenuation * d * d);

	//see if point on surface is inside cone of illumination
	spotDot = dot(-VP,gl_LightSource[i].spotDirection);
	if(spotDot < gl_LightSource[i].spotCosCutoff)
		spotAttenuation = 0.0;
	else
		spotAttenuation = pow(spotDot,gl_LightSource[i].spotExponent);

	//combine the spotlight and distance attenuation
	attenuation *= spotAttenuation;

	halfVector = normalize(VP + eye);

	nDotVP = max(0.0, dot(normal,VP));
	nDotHV = max(0.0, dot(normal,halfVector));

	if(nDotVP == 0.0)
		pf = 0.0;
	else
		pf = pow(nDotHV, gl_FrontMaterial.shininess);

	ambient += gl_LightSource[i].ambient;
	diffuse += gl_LightSource[i].diffuse  * nDotVP * attenuation;
	specular += gl_LightSource[i].specular * pf * attenuation;
}

//......------=========================================================------......
//            Iterate through all lights and accumulate each one's contribution
//==================================================================== 
void PerformBasicLighting()
{
	//Perform lighting calculations
	vec4 amb;
	vec4 diff;
	vec4 spec;
	//clear the light intensity accumulators
	amb = vec4(0.0);
	diff   = vec4(0.0);
	spec= vec4(0.0);

	//int i = 0;

	//loop through all lights, compute contribution from each.
	for(int i=0; i < 8.0; i++) //hardcoded at the moment (8.0 = Maximum lights in scene)
	{
		if(lightEnabled[i] != 0) 
		{
		
			
		if(gl_LightSource[i].position.w == 0.0)
			DirectionalLight(i,normal,amb,diff,spec);
		
		else if(gl_LightSource[i].spotCutoff == 180.0)
			PointLight(i,normal, amb, diff, spec);
		
		else
			SpotLight(i,normal, amb, diff, spec);
		}
	}

	vec4 color;
	color = gl_FrontMaterial.diffuse * gl_LightModel.ambient + 
		/*amb * gl_FrontMaterial.ambient + */
		diff * gl_FrontMaterial.diffuse;

	color += spec * gl_FrontMaterial.specular;

	color.a = gl_FrontMaterial.diffuse.a;

	gl_FrontColor = color;
}

//#####################################################################################################   TEXTURING
//......------=========================================================------......
//			Calculate Sphere Map texture Coordinates
//====================================================================	
vec2 SphereMap(in vec3 ecPosition3, in vec3 normal)
{
	float m;
	vec3 r,u;
	u = normalize(ecPosition3);
	r = reflect(u,normal);
	m = 2.0*sqrt(r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0));
	return vec2 (r.x / m + 0.5, r.y / m + 0.5);
}

//......------=========================================================------......
//			Calculate Reflection Map texture Coordinates
//====================================================================
vec3 ReflectionMap(in vec3 ecPosition3, in vec3 normal)
{
	//float NdotU,m;
	vec3 u;
	u = normalize(ecPosition3);
	return (reflect(u,normal));
}

//......------=========================================================------......
//				Generate Texture Coordinates
//====================================================================
void TexCoordGen()
{

	const int PROJECTIVE = 0;
	const int REFLECTIVE = 1;
	vec3 reflection;
	vec2 sphereMap;

	for(int i=0; i < 4; i++)
	{
		if(textureInfo[i].enabled != 0)
		{
			/*if(textureInfo[i].method == PROJECTIVE)
			{
				gl_TexCoord[i].s = dot(ecPosition,gl_EyePlaneS[i]);
				gl_TexCoord[i].t = dot(ecPosition,gl_EyePlaneT[i]);
				gl_TexCoord[i].p = dot(ecPosition,gl_EyePlaneR[i]);
				gl_TexCoord[i].q = dot(ecPosition,gl_EyePlaneQ[i]);
			}*/
			if(textureInfo[i].method == REFLECTIVE)
			{
				reflection = ReflectionMap(ecPosition3,normal);
				gl_TexCoord[i] = vec4(reflection,1.0);
			}
			 
			else if(textureInfo[i].method == -1)
			{
				gl_TexCoord[i] = gl_MultiTexCoord0;
			}
		
			gl_TexCoord[i] *= gl_TextureMatrix[i];
		}
	}		
}	

//####################################################################################################     MAIN
void main()
{
	gl_Position = ftransform();
	gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;

	ecPosition = gl_ModelViewMatrix*gl_Vertex;
	ecPosition3 = (vec3 (ecPosition)) / ecPosition.w;

	eye = -normalize(ecPosition3);

	normal = normalize(gl_NormalMatrix * gl_Normal);
	normal *= gl_NormalScale;

	PerformBasicLighting();

	TexCoordGen();
} 

I’m sort of at a loss. I’m hoping it’s driver issues.

it seems that your vertex shader is computing per vertex things that are invariant per mesh.

for instance the texture info or the light types/number should not be declared as uniform parameter. They should be inlined for your specific lighting equation.

The fixed function equivalent probably has a dedicated shader per combination of light types/texture type.

Pierre B.

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