PDA

View Full Version : Strange struct behavior



Asmodeus
06-15-2016, 10:06 AM
Hey, i have a strange behavior with my Light Structures. The problem is the following: I have one in/out struct LightComponents (which had initially 2 components - color and to light vector) and another structure LightTransformed .The lighting was working find until i decided to add another component attenuation to the LightComponents struct. For some unknown reason adding this somehow corrupts the other structure(LightTransformed) which is no way connected to the LightComponents. I managed to pin point the location where the data gets corrupted.

Basically: If i keep the attenuation it gets f*^$%d up the line that's causing the problem is : "vec3 unitToCamera = (normalize(lightTransf.ToCamera)).xyz;"(if i replace unitToCamera with hard coded value it works). if i remove the attenuation completely from the LightComponents the lighting calculations pass and work fine without any adjustments.

Bits from the Fragment shader


in struct LightTransformed {
vec4 Normal;
vec4 ToCamera;
} lightTransf;

in struct LightComponents {
vec4 ToLight;
vec4 DirLightColor;
vec4 Attenuation;
} lightData[10];

float calculateDirSpecularFactor(vec3 unitNormal,vec3 unitToLight,vec3 unitToCamera) {
vec3 invToLight = -unitToLight;
vec3 reflected = reflect(invToLight,unitNormal);
float specFactor = dot(unitToCamera,reflected);
float brightness = pow(max(specFactor,0.0),90.0);
return brightness;
}

LightColor calculateDirLightColor(LightTransformed lightTransf, LightComponents lightComponents) {
LightColor finalColor;
//float distance = length(lightTransf.ToCamera);
//vec4 attFactor = lightComponents.Attenuation;
vec3 unitNormal = (normalize(lightTransf.Normal)).xyz;
vec3 unitToCamera = (normalize(lightTransf.ToCamera)).xyz;
vec3 unitToLight = (normalize(lightComponents.ToLight)).xyz;
finalColor.diffuseColor = lightComponents.DirLightColor * calculateDirDiffuseFactor(unitNormal,unitToLight);
finalColor.specularColor = lightComponents.DirLightColor * calculateDirSpecularFactor(unitNormal,unitToLight, unitToCamera);
finalColor.ambientColor = vec4(0.2);
return finalColor;
}


Now if that is not weird enough here is another very strange thing if i use the first part of the code to generate the final color of the light(s), the code works even with the attenuation and the problems from above are not present. If i use the for loop function to generate the final color of the light(s) the same problem arises. Note here that the for loop works when the attenuation is not present in the structure




LightColor light;
LightColor light1 = calculateDirLightColor(lightTransf,lightData[0]);
LightColor light2 = calculateDirLightColor(lightTransf,lightData[1]);
light.diffuseColor = light1.diffuseColor + light2.diffuseColor;
light.specularColor = light2.specularColor + light2.specularColor;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

LightColor calculateAllLights(LightTransformed lightTransf,LightComponents lightComponents[10]) {
LightColor finalLight;
for(int i=0; i<10; ++i) {
LightColor curLight = calculateDirLightColor(lightTransf,lightComponents[i]);
finalLight.diffuseColor = finalLight.diffuseColor + curLight.diffuseColor;
finalLight.specularColor = finalLight.specularColor + curLight.specularColor;
}
finalLight.ambientColor = vec4(0.2);
return finalLight;
}



Bottom Line: No attenuation - no problems, every bit of code gets compiled and works just fine, with attenuation in the struct i have to remove the for loop to make it work (which is not very desired) . For me this makes exactly 0 sense !!!!

Vertex Shader, the way i fill up those two structures


LightTransformed calculateLightTransformed(mat4 modelMatrix,mat4 viewMatrix,vec4 pos, vec3 normal) {
LightTransformed lightTransf;
lightTransf.ToCamera = inverse(viewMatrix) * vec4(0.0,0.0,0.0,1.0) - pos;
lightTransf.Normal = modelMatrix * vec4(normal,0);
return lightTransf;
}

LightComponents calculateDirLightComponents(DirLightData dirLight,vec4 pos) {
LightComponents lightComponent;
lightComponent.DirLightColor = dirLight.color;
lightComponent.Attenuation = dirLight.attenuation;
lightComponent.ToLight = dirLight.lightpos - pos;
return lightComponent;
}

Cornix
06-15-2016, 11:21 AM
How do you upload your data to your shader? Might it be that you did not update your CPU side code correctly to reflect the changes to your struct?

Asmodeus
06-15-2016, 12:15 PM
Forgot to add that up, i am using uniform buffers to upload the data.



auto offset = 0;
dirlightBuffer.bindBuffer();
auto componentSize = (3 * sizeof(glm::vec4));
auto size = componentSize * dirLights.size();
dirlightBuffer.allocateBuffer(size, GL_DYNAMIC_DRAW);
for (size_t i = 0; i < dirLights.size(); i++)
{
dirlightBuffer.bufferSubData(dirLights[i]->getColor(), 0 + offset);
dirlightBuffer.bufferSubData(dirLights[i]->calculateModelMatrix() * glm::vec4(1), sizeof(glm::vec4) + offset);
dirlightBuffer.bufferSubData(dirLights[i]->getAttenuation(), (sizeof(glm::vec4) * 2) + offset);
offset += componentSize;
}
dirlightBuffer.unbindBuffer();


struct DirLightData {
vec4 color;
vec4 lightpos;
vec4 attenuation;
};

layout(std140) uniform DirLightBlock {
DirLightData dirLight[10];
};


That is the light comming from the OpenGL code, but i have tested the values inside this struct and it seems fine and correct. Ignore the naming, it is badly selected