Jump to content
  • Advertisement
Sign in to follow this  
StockwellSteve

Strange Problem - CG Related

This topic is 4162 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

Dear All I've come across a strange problem in my program and wondered if someone could help out. I have a scene consisting of a bunch of houses. To begin with I constructed this entire scene as one single model. I have a CG fragment shader which performs lighting in this scene. In this incarnation, the shader was doing its job fantastically and everything was correctly lit. Now, I have broken up my scene and am rendering individual objects and moving them about in the scene and will save their co-ordinates in a text file which my scene class will then read back in and reconstruct the scene appropriately. So as far as scene construction goes, all well and good. However, I've noticed aproblem with the lighting. As I said before when the scene was one single model, thing lit well. As I moved the light around, the differing objects in the scene lit correctly. Now that I've broken things up its a different matter. I can place my light in front of a house, lets call it House A. I then create another house, House B and position it far from House A. However, with the movable light positioned directly in front of House A, so close that I can see the light source clearly, the light also appears in exactly the same spot in the front of House B despite being far from it. No matter how I move House B around, the light stays on the front of House B. So basically it reflects House A. I've also just noticed that if i have a blank scene with the light at approx 0,0,0 and i place the house just behind this (with just this one house in the scene)so the house is lit, I move this one house away from the light and the same thing happens - it stays lit in the same place no matter how far from the light. Any idea why this may be happening? Thanks

Share this post


Link to post
Share on other sites
Advertisement
It's possible that you're inadvertently specifying the light's position in object space, as opposed to world space. This wasn't a problem when the whole scene was one model because there was only one coordinate space for all the houses, but now that each house has a unique yet identical local space, it will light all the instances the same. Without the actual transformation code or knowing which matrices you're using it's hard to tell, but to me this sounds like the most likely culprit.

Share this post


Link to post
Share on other sites
Well I pass the modelview projection matrix into the shader and the lighting calculations are being done based on that. Should I be working with just the projection matrix?

Share this post


Link to post
Share on other sites
When you say the lighting calculations are based on that matrix, do you mean you transform the light with the same matrix you transform the house geometry? Because that could lead to a problem if you're instancing the house. Could you post a few snippets of code showing the transformations?

Share this post


Link to post
Share on other sites


//my fragment program

void main(float4 position : TEXCOORD1,
float3 normal : TEXCOORD2,
float2 texCoord : TEXCOORD0,

out float4 color : COLOR,

uniform float3 globalAmbient,
uniform float3 lightColor,
uniform float3 lightPosition,
uniform float3 eyePosition,
uniform float3 Ke,
uniform float3 Ka,
uniform float3 Kd,
uniform float3 Ks,
uniform float shininess,
uniform float Kc,
uniform float Kl,
uniform float Kq,
uniform sampler2D decal)
{
float3 P = position.xyz;
float3 N = normalize(normal);

float3 emissive = Ke;

float3 ambient = Ka * globalAmbient;

float3 L = normalize(lightPosition - P);
float diffuseLight = dot(N,L);
float3 diffuse = Kd * lightColor * diffuseLight;

float3 V = normalize(eyePosition - P);
float3 H = normalize(L + V);
float specularLight = pow(max(dot(N,H), 0), shininess);

if (diffuseLight <=0) specularLight = 0;

float3 specular = Ks * lightColor * specularLight;
float d = distance(P, lightPosition);
float attenuationFactor = 1/(Kc + Kl * d + Kq * d * d);

color.xyz = tex2D(decal, texCoord) * (emissive+ attenuationFactor * (diffuse + ambient + specular));
color.w = 1;
}

//my vertex program

void main(float4 position : POSITION,
float3 normal : NORMAL,
float2 leftTexCoord : TEXCOORD0,

out float4 oPosition : POSITION,
out float2 oLeftTexCoord: TEXCOORD0,
out float3 objectPos : TEXCOORD1,
out float3 oNormal : TEXCOORD2,

uniform float4x4 modelViewProj)
{
oPosition = mul(modelViewProj, position);
objectPos = position.xyz;
oLeftTexCoord = leftTexCoord;
oNormal = normal;
}


//my render method

void Model_3DS::Draw()
{
if (visible)
{
// Move the model
glTranslatef(pos.x, pos.y, pos.z);

// Rotate the model
glRotatef(rot.x, 1.0f, 0.0f, 0.0f);
glRotatef(rot.y, 0.0f, 1.0f, 0.0f);
glRotatef(rot.z, 0.0f, 0.0f, 1.0f);

glScalef(scale, scale, scale);

// Loop through the objects
for (int i = 0; i < numObjects; i++)
{
// Enable texture coordiantes, normals, and vertices arrays
if (Objects.textured)
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if (lit)
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

// Point them to the objects arrays
if (Objects.textured)
glTexCoordPointer(2, GL_FLOAT, 0, Objects.TexCoords);
if (lit)
glNormalPointer(GL_FLOAT, 0, Objects.Normals);
glVertexPointer(3, GL_FLOAT, 0, Objects.Vertexes);

// Loop through the faces as sorted by material and draw them
for (int j = 0; j < Objects.numMatFaces; j ++)
{
// Use the material's texture
Materials[Objects.MatFaces[j].MatIndex].tex.Use();

glPushMatrix();

// Move the model
glTranslatef(Objects.pos.x, Objects.pos.y, Objects.pos.z);

// Rotate the model
//glRotatef(Objects.rot.x, 1.0f, 0.0f, 0.0f);
//glRotatef(Objects.rot.y, 0.0f, 1.0f, 0.0f);
//glRotatef(Objects.rot.z, 0.0f, 0.0f, 1.0f);

glRotatef(Objects.rot.z, 0.0f, 0.0f, 1.0f);
glRotatef(Objects.rot.y, 0.0f, 1.0f, 0.0f);
glRotatef(Objects.rot.x, 1.0f, 0.0f, 0.0f);

cgGLSetTextureParameter(decal, Materials[Objects.MatFaces[j].MatIndex].tex.texture[0]);
cgGLSetStateMatrixParameter(modelViewProj, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
cgGLEnableProfile(VertexProfile);
cgGLEnableProfile(FragmentProfile);
cgGLBindProgram(VertexProgram);
cgGLBindProgram(FragmentProgram);
cgGLSetParameter4f(lightColor, 1.0f, 0.98f, 0.609f, 1.0f);
//cgGLSetParameter4f(globalAmbient, 1.0f, 1.0f, 1.0f, 1.0f);
cgGLSetParameter4f(lightPosition, light->x, light->y, light->z, 1.0f);
cgGLSetParameter4f(eyePosition, camera->eye.x, camera->eye.y, camera->eye.z, 1.0f);

cgGLSetParameter4f(Ks, 1.0f, 1.0f, 1.0f, 1.0f);
cgGLSetParameter4f(Ka, 1.0f, 1.0f, 1.0f, 1.0f);
cgGLSetParameter4f(Kd, 1.0f, 1.0f, 1.0f, 1.0f);
cgGLSetParameter1f(Kc, 1.0f);
cgGLSetParameter1f(Kl, 0.05f);
cgGLSetParameter1f(Kq, 0.0f);
cgGLEnableTextureParameter(decal);

// Draw the faces using an index to the vertex array
glDrawElements(GL_TRIANGLES, Objects.MatFaces[j].numSubFaces, GL_UNSIGNED_SHORT, Objects.MatFaces[j].subFaces);

cgGLDisableProfile(VertexProfile);
cgGLDisableProfile(FragmentProfile);


glPopMatrix();
}

Share this post


Link to post
Share on other sites
I think I see the problem. You have to remember that none of the OpenGL transformation calls will automatically apply to any vertices when you're using the programmable pipeline. All those calls to glRotate/glTranslate/glScale are only so that the internal transform state is what you want it to be when you call cgGLSetStateMatrixParameter.

In your vertex program, you pass-though the vertex position as TEXCOORD1. However this vertex has not been transformed at all, and is whatever value existed in your vertex array. So no matter what other transformations you did, since all values in the vertex array are the same for each object (all in object space), it's going to light them all the same.

What you want to do is pass down two matrices, modelViewProj (transformation from object-space to clip-space), and viewProjInv (transformation from clip-space to world-space). The idea is to put the vertices into world-space with the light. The second matrix looks a little weird, but given the way you set up OpenGL transformations it's actually easier to get to world-space from clip-space than it is from object-space. Try adding this line right before the object for-loop (after setting up the appropriate matrix parameter of course):

cgGLSetStateMatrixParameter(viewProjInv, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_INVERSE);

And in the vertex shader, modify the pass-through line to this:

objectPos = mul(viewProjInv, oPosition).xyz;

Hopefully I've gotten everything correct, give it a try and let us know how it goes :)

Share this post


Link to post
Share on other sites
Hi Zipster,

Thanks again for replying - your help is invaluable to me.

I've tried making the changes you advised but no cookie unforunately.


After the changes you suggested, without moving my light, I move an object in the scene and the lighting stays the same on it whereever it is :(

Its taken all my strength not to just start hacking around - I really can't see the problem.

Can you post images on here? Maybe it would help if you could see the problem?

Share this post


Link to post
Share on other sites
I just noticed that you're transforming both the object and then each individual side, so I told you put the cgGLSetStateMatrixParameter call in the wrong place; it should go first thing inside the if-block. In the broader sense, it should go first thing after the view transformation has been set (i.e. with gluLookAt), so I'm assuming you haven't done anything else between setting the view transform and calling the Draw() method.

Share this post


Link to post
Share on other sites
Hi Zipster,

Well thats definately made progress but still not quite there.

If i move my new house away after I've created it then the lighting now fades instead of staying there.

I now have a curious problem of the fact that if i create a duplicated house at a location away from the origin (where the first house was created) it lights it as if it WERE at the origin!! Odd.

I'll try and sort that one out. If you have any suggestions though i'd be pleased to hear.

If you ever need anything from over in the UK zipster give me a shout and i'll sort you out - thanks so much for everything.

Share this post


Link to post
Share on other sites
Without examining the source code, all I can say is to make sure you know which coordinate system your values are in at all times, because you can only perform meaningful calculations on values in the same system. The light fade you're experiencing is expected, since you have an attenuation factor in your lighting code. However I'm surprised the lighting didn't work for the second case you mentioned. The inverse view/projection transformation is identical for all geometry in any given view, so it should put all geometry n world-space no matter which space it started in (object, world, etc.).

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!