Basic per-fragment lighting with cg shader

Started by
5 comments, last by Zische 18 years, 8 months ago
hi, i've made a vertex program and a fragment program to bring multitexturing and per-fragment lighting to my 3d-app. unfortunately there is a problem with the spaces. in the vertex program i compute the vertices' world space position by multiplying the vertices with the modelviewproj matrix which is currently 1 0 0 0 0 1 0 0 0 0 1 -5 0 0 0 0. there are four vertices which represent two triangles formed to a quad(-1,-1,1,1). for the per-pixel lighting i need the fragment's position in world space because the viewer's position and the light position is in world space, too. so i specify an output variable with the semantic TEXCOORD2 in the vertex program and a corresponding input variable in the fragment program. when i set the positions for each vertex, the rasterizer should give me an interpolated position for each fragment. but this doesn't seep to work properly. the z value is clamped to [0..1]. i have done everything exactly like what is in the nvidia's cg tutorial book. except that i use world space positions in the fragment shader. here is my code:
***************
VERTEX
***************

void mainV	(	
				float4				iPosition : POSITION,
				float4				iNormal : NORMAL,
				float3				iTexCoord1 : TEXCOORD0,
				float3				iTexCoord2 : TEXCOORD1,
				
				uniform float4x4	iModelViewProj,
				
				out float4			oPosition : POSITION,
				out float3			oTexCoord1 : TEXCOORD0,
				out float3			oTexCoord2 : TEXCOORD1,
				out float3			oVertexPos : TEXCOORD2,
				out float3			oVertexNormal : TEXCOORD3
			)
{
	oPosition = mul(iModelViewProj, iPosition);
	oTexCoord1 = iTexCoord1;
	oTexCoord2 = iTexCoord2;
	oVertexPos = iPosition.xyz;
	oVertexNormal = iNormal.xyz;
}


******************
FRAGMENT
******************

float3 light(
				float3 iLightPos,
				float3 iLightCol,
				float3 iMaterial[5],
				float3 iFragmentPosition,
				float3 iFragmentNormal,
				float3 iEyePosition
			)
{
	float3 final = iMaterial[3];
	final += iMaterial[0] * iLightCol;
	
	float3 Normal = normalize(iFragmentNormal);
	float3 L = normalize(iLightPos - iFragmentPosition);
	float Diffuse = max(dot(Normal, L), 0);
	final += iMaterial[1] * iLightCol * Diffuse;
	
	float3 V = normalize(iEyePosition - iFragmentPosition);
	float3 H = normalize(L + V);
	float Specular = pow(max(dot(Normal, H), 0), iMaterial[4].x);
	final += iMaterial[1] * iLightCol * Diffuse;
	
	float d = distance(iLightPos, iFragmentPosition);
	
	return final / ( d * 0.25);
}

void mainF	(	
				float3				iTexCoord1 : TEXCOORD0,
				float3				iTexCoord2 : TEXCOORD1,
				float4				iFragmentPos : TEXCOORD2,
				float3				iFragmentNormal : TEXCOORD3,
				
				uniform float3		iEyePosition,
				uniform float4		iLightPos[4],
				uniform float4		iLightCol[4],
				uniform float3		iMaterial[5],
				uniform sampler2D	iTexture1,
				uniform sampler2D	iTexture2,
				
				out float4			oColor : COLOR
			)
{
	float4 Tex1 = tex2D(iTexture1, iTexCoord1.xy);
	float4 Tex2 = tex2D(iTexture2, iTexCoord2.xy);
	oColor = float4(lerp(Tex1.rgb, Tex2.rgb, Tex2.a), 1);
	
	iFragmentPos *= 0.1;
	
	float3 Light = float3(1,1,1);
	if(iLightPos[0].w>0.0) Light  = light(iLightPos[0].xyz, iLightCol[0].rgb, iMaterial, iFragmentPos.xyz, iFragmentNormal, iEyePosition);
	if(iLightPos[1].w>0.0) Light += light(iLightPos[1].xyz, iLightCol[1].rgb, iMaterial, iFragmentPos.xyz, iFragmentNormal, iEyePosition);
	if(iLightPos[2].w>0.0) Light += light(iLightPos[2].xyz, iLightCol[2].rgb, iMaterial, iFragmentPos.xyz, iFragmentNormal, iEyePosition);
	if(iLightPos[3].w>0.0) Light += light(iLightPos[3].xyz, iLightCol[3].rgb, iMaterial, iFragmentPos.xyz, iFragmentNormal, iEyePosition);
	oColor = float4(Light, 1);
}

[Edited by - Zische on August 21, 2005 6:16:29 PM]
Advertisement
don´t know anything about fragments, but I noticed something in your code:
shouldn´t
oColor = float4(Light,1);

be
oColor = oColor * float4(Light,1);

? It´s the last line of MainF()... perhaps that helps.
You are right. I changed it for debugging, but this doesn't create the error. It rather helps me by showing the light's color instead of a shaded texture.
Quote:Original post by Zische
[...]the modelviewproj matrix which is currently
1 0 0 0
0 1 0 0
0 0 1 -5
0 0 0 0.


How is it possible, that your matrix is singular (determinant==0)? Where did you get it from?

Quote:
for the per-pixel lighting i need the fragment's position in world space because the viewer's position and the light position is in world space, too.


So shouldn't it be:
[...]uniform float4x4 iModelViewProj,uniform float4x4 iModel,out float4 oPosition : POSITION,[...]oPosition = mul(iModelViewProj, iPosition);oTexCoord1 = iTexCoord1;oTexCoord2 = iTexCoord2;oVertexPos =  mul( iModel, iPosition );oVertexNormal =  mul( (float3x3)iModel, (float3)iNormal );


Unless you're sure the model matrix is identity, which is usually not the case.
~def
im not so familiar with all thos matrices. the determinatn 0 was a mistake while i wrote the thread. here is what i do to pass the modelviewproj matrix to the shader:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMultMatrix(m_Transformation);
cgGLSetStateMatrixParameter(m_modelViewMatrix, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);


there were several mistakes in my code due to "brute force" debugging. here is the code:

***********VERTEX***********void main	(					float4				iPosition : POSITION,				float4				iNormal : NORMAL,				float3				iTexCoord1 : TEXCOORD0,				float3				iTexCoord2 : TEXCOORD1,								uniform float4x4	iModelViewProj,				uniform float4x4	iModel,								out float4			oPosition : POSITION,				out float3			oTexCoord1 : TEXCOORD0,				out float3			oTexCoord2 : TEXCOORD1,				out float3			oVertexPos : TEXCOORD2,				out float3			oVertexNormal : TEXCOORD3			){	oPosition = mul(iModelViewProj, iPosition);	oTexCoord1 = iTexCoord1;	oTexCoord2 = iTexCoord2;	oVertexPos = mul(iModel, oPosition).xyz;	oVertexNormal = mul((float3x3)iModel, iNormal.xyz);}***********Fragment***********float3 light(				float3 iLightPos,				float3 iLightCol,				float3 iMaterial[5],				float3 iFragmentPosition,				float3 iFragmentNormal,				float3 iEyePosition			){	float3 final = iMaterial[3];	final += iMaterial[0] * iLightCol;		float3 Normal = normalize(iFragmentNormal);	float3 L = normalize(iLightPos - iFragmentPosition);	float Diffuse = max(dot(Normal, L), 0);	final += iMaterial[1] * iLightCol * Diffuse;		float3 V = normalize(iEyePosition - iFragmentPosition);	float3 H = normalize(L + V);	float Specular = pow(max(dot(Normal, H), 0), iMaterial[4].x);	if(Diffuse<=0) Specular = 0;	final += iMaterial[2] * iLightCol * Specular;		float d = distance(iLightPos, iFragmentPosition);		return final / ( d * 0.25);}void main	(					float3				iTexCoord1 : TEXCOORD0,				float3				iTexCoord2 : TEXCOORD1,				float4				iFragmentPos : TEXCOORD2,				float3				iFragmentNormal : TEXCOORD3,								uniform float3		iEyePosition,				uniform float4		iLightPos[4],				uniform float4		iLightCol[4],				uniform float3		iMaterial[5],				uniform sampler2D	iTexture1,				uniform sampler2D	iTexture2,								out float4			oColor : COLOR			){	float3 Light = float3(1,1,1);	Light = light(iLightPos[0].xyz, iLightCol[0].rgb, iMaterial, iFragmentPos.xyz, iFragmentNormal, iEyePosition);	oColor = float4(Light, 1);}


the diffuse color works. but the specular is 0.

[Edited by - Zische on August 22, 2005 11:16:48 AM]
Don't take me wrong, but your code is quite confusing, and thus hard to debug.
Material[0], Material[1], Material[2], Material[3]. There are plenty of letters in the alphabet and plenty of words in a dictionary [grin].

Now seriously, what's with the iModel matrix? Are you setting it properly? In GL, you do not have explicitly model matrix (only model*view), so you got to keep track of it by yourself.

And why can't you simply debug your shader step-by-step? Or is there no such option in CG?
~def
i dont know how to use nvidia's IDE FX Composer and i don't know how to implement cg compiling in microsoft's visual c++, so it is hard to debug, because i have to run cgc.exe everytime i want to debug syntax errors. but i cant really see what values are in the variables at runtime.

the iMaterial array is to collect information like ambient, diffuse, specular, emissive, shininess, alpha.

thanks for your help. i made it work now.

This topic is closed to new replies.

Advertisement