Jump to content
  • Advertisement
Sign in to follow this  
Zische

Basic per-fragment lighting with cg shader

This topic is 4834 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!