Распознать любые логические ошибки? Есть предложения по улучшению этого кода или улучшению результатов?
Образ: До & После
Видео: Короткое видео, демонстрирующее текущие результаты картографирования!
Нормальные и касательные векторы, отправляемые в вершинный шейдер, верны.
Метод во фрагментном шейдере:
vec3 processPointLight(in vec3 norm, in vec3 pos, in int lightIndex)
{
float distance = length(lights[lightIndex].Position.xyz - pos.xyz);
//Light Attenuation Computation
float attenuation = 1.0f / (
(lights[lightIndex].AttenuationConst +
lights[lightIndex].AttenuationLinear * distance +
lights[lightIndex].AttenuationQuad * distance * distance));
vec3 textureDifResult;
vec3 textureSpecResult;
if (Toggle_Textures)
{
vec3 textureNrmResult;
textureDifResult = textureLod(Texture0, ((fs_in.textureCoord.xy * (vec2(1024) / vec2(7168))) + (vec2(1024) * (fs_in.textureUnits.x + 0)) / vec2(7168)), 0).rgb;
textureNrmResult = textureLod(Texture0, ((fs_in.textureCoord.xy * (vec2(1024) / vec2(7168))) + (vec2(1024) * (fs_in.textureUnits.x + 1)) / vec2(7168)), 0).rgb;
textureSpecResult = textureLod(Texture0, ((fs_in.textureCoord.xy * (vec2(1024) / vec2(7168))) + (vec2(1024) * (fs_in.textureUnits.x + 2)) / vec2(7168)), 0).rgb;
// Transform normal vector to range [-1,1]
norm = (textureNrmResult * 2.0f - vec3(1.0f));
}
else
{
textureDifResult = ModelColor.rgb;
textureSpecResult = ModelColor.rgb;
}
//viewPoint, normal, tangent and bitangent are in view space so we need to transform the light's position to view space too.. Special thanks to pleup!
vec3 L =normalize( mat3(fs_in.mv_Matrix) * lights[lightIndex].Position.xyz ) - fs_in.viewPoint;
vec3 lightDir = normalize(vec3(dot(L, fs_in.tangent.xyz), dot(L, fs_in.bitangent.xyz), dot(L, norm)));
vec3 reflection = reflect(-L, norm);
// Light Diffuse Computation
vec3 diffuse = ( max(0.0f, dot( norm ,lightDir )) * lights[lightIndex].Diffuse * textureDifResult);
// Light Ambience Computation
vec3 ambient = lights[lightIndex].Ambient;
// Light Specular Computation
vec3 specular = vec3(0.0f, 0.0f, 0.0f);
//if (dot(lightDir , norm ) > 0.0f)
specular = pow(max(0.0f, dot(reflect(-lightDir, norm), fs_in.eyeDir.xyz )), 20.0) * textureSpecResult * lights[lightIndex].Specular * lights[lightIndex].SpecularPower;
return min((ambient)+attenuation * (diffuse + specular), vec3(1.0));
}
Полный вершинный шейдер:
#version 420 core
layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_TexCoord;
layout(location=2) in vec4 in_Normal;
layout(location=3) in vec4 in_Tangent;
layout(location=4) in uvec4 in_TextureUnits;
// per frame
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;
uniform vec4 EyePosition;
// per item
uniform mat4 ModelMatrix;
uniform mat4 ModelMatrixOrientation;out VS_OUT
{
vec4 eyePosition;
vec4 worldPosition;
vec4 normal;
vec4 tangent;
vec4 bitangent;
vec4 eyeDir;
vec3 textureCoord;
flat uvec4 textureUnits;
vec3 viewPoint;
mat4 mv_Matrix;
} vs_out;
void main()
{
gl_Position = ModelMatrix * in_Position;
vs_out.worldPosition = ModelMatrix * in_Position;
vs_out.eyePosition = ProjectionMatrix * ViewMatrix * ModelMatrix * in_Position;
vs_out.textureCoord = vec3(in_TexCoord.x, in_TexCoord.y, in_TexCoord.z);
vs_out.textureUnits = in_TextureUnits;
gl_Position = ProjectionMatrix * ViewMatrix * gl_Position;vs_out.mv_Matrix = ViewMatrix * ModelMatrix;
//vertex Position in view space..
vec4 P = vs_out.mv_Matrix * in_Position;
vs_out.viewPoint= P.xyz;
vs_out.normal = normalize(vec4(mat3( vs_out.mv_Matrix) * in_Normal.xyz, 1.0f));
// Calculate normal (N) and tangent (T) vectors in view space from incoming object space vectors.
vs_out.tangent = normalize(vec4(mat3( vs_out.mv_Matrix ) * in_Tangent.xyz, 1.0f) );
// Calculate the bitangent vector (B) from the normal and tangent vectors
vs_out.bitangent = vec4( cross(vs_out.normal.xyz, vs_out.tangent.xyz), 1.0f);
// The view vector is the vector from the point of interest to the viewer, which in view space is simply the negative of the position.
// Calculate that and multiply it by the TBN matrix.
vec3 V = -P.xyz;
vs_out.eyeDir = normalize(vec4(dot(V, vs_out.tangent.xyz), dot(V, vs_out.bitangent.xyz), dot(V, vs_out.normal.xyz),1.0f));
return;
}
Световые свойства:
<LightComponent type="PointLight" isEnabled="1" specularPower="1.0f" offsetX="0.0f" offsetY="40.0f" offsetZ="0.0f" ambientR="0.0f" ambientG="0.0f" ambientB="0.0f" diffuseR="0.3f" diffuseG="0.3f" diffuseB="0.3f" specularR="0.3f" specularG="0.3f" specularB="0.3f" attenConst="0.3f" attenLinear="0.000091427f" attenQuad="0.0000065429f" />
Функция менеджера текстур, которая загружает текстуры:
void cTextureManager::loadTextureMipmap(rapidxml::xml_node<>* textureNode){
std::string pathDif = textureNode->first_attribute("pathDif")->value();
std::string pathNrm = textureNode->first_attribute("pathNrm")->value();
std::string pathSpec = textureNode->first_attribute("pathSpec")->value();
FREE_IMAGE_FORMAT imgFormat = FreeImage_GetFileType(pathDif.c_str(), 0);//Get current format (assume all textures are the same format)
FIBITMAP* imagenDif = FreeImage_Load(imgFormat, pathDif.c_str());
imagenDif = FreeImage_ConvertTo32Bits(imagenDif);
FIBITMAP* imagenNrm = FreeImage_Load(imgFormat, pathNrm.c_str());
imagenNrm = FreeImage_ConvertTo32Bits(imagenNrm);
FIBITMAP* imagenSpec = FreeImage_Load(imgFormat, pathSpec.c_str());
imagenSpec = FreeImage_ConvertTo32Bits(imagenSpec);
int width = FreeImage_GetWidth(imagenDif); // Assume images are the same size..
int height = FreeImage_GetHeight(imagenDif);
GLubyte* textureDif = new GLubyte[4 * width*height];
GLubyte* textureNrm = new GLubyte[4 * width*height];
GLubyte* textureSpec = new GLubyte[4 * width*height];
char* pixelsDif = (char*)FreeImage_GetBits(imagenDif);
char* pixelsNrm = (char*)FreeImage_GetBits(imagenNrm);
char* pixelsSpec = (char*)FreeImage_GetBits(imagenSpec);
//FreeImage loads in BGR format, so you need to swap some bytes(Or use GL_BGR).
for (int j = 0; j<width*height; j++) {
textureDif[j * 4 + 0] = pixelsDif[j * 4 + 2];
textureDif[j * 4 + 1] = pixelsDif[j * 4 + 1];
textureDif[j * 4 + 2] = pixelsDif[j * 4 + 0];
textureDif[j * 4 + 3] = pixelsDif[j * 4 + 3];
textureNrm[j * 4 + 0] = pixelsNrm[j * 4 + 2];
textureNrm[j * 4 + 1] = pixelsNrm[j * 4 + 1];
textureNrm[j * 4 + 2] = pixelsNrm[j * 4 + 0];
textureNrm[j * 4 + 3] = pixelsNrm[j * 4 + 3];
textureSpec[j * 4 + 0] = pixelsSpec[j * 4 + 2];
textureSpec[j * 4 + 1] = pixelsSpec[j * 4 + 1];
textureSpec[j * 4 + 2] = pixelsSpec[j * 4 + 0];
textureSpec[j * 4 + 3] = pixelsSpec[j * 4 + 3];
}
int tempMipmapLevel = gCurrentMipmapLevel;
std::string name = textureNode->first_attribute("name")->value();
gMap_TextureNameToMipmapLevel[name] = tempMipmapLevel;
gCurrentMipmapLevel+= 3;
// Assume the texture is already bound to the GL_TEXTURE_2D target
glTexSubImage2D(GL_TEXTURE_2D, // 2D texture
0, // Level 0
(1024 * tempMipmapLevel), (1024 * tempMipmapLevel), // Offset 0, 0
1024, 1024, // 1024 x 1024 texels
GL_RGBA, // Four channel data
GL_UNSIGNED_BYTE, // Floating point data
(GLvoid*)textureDif); // Pointer to data
delete [] textureDif;
// Assume the texture is already bound to the GL_TEXTURE_2D target
glTexSubImage2D(GL_TEXTURE_2D, // 2D texture
0,
1024 * (tempMipmapLevel+1), 1024 * (tempMipmapLevel+1),
1024, 1024,
GL_RGBA,
GL_UNSIGNED_BYTE,
(GLvoid*)textureNrm);
delete[] textureNrm;
// Assume the texture is already bound to the GL_TEXTURE_2D target
glTexSubImage2D(GL_TEXTURE_2D, // 2D texture
0,
1024 * (tempMipmapLevel +2), 1024 * (tempMipmapLevel+2),
1024, 1024,
GL_RGBA,
GL_UNSIGNED_BYTE,
(GLvoid*)textureSpec);
delete[] textureSpec;// int MaxTextureImageUnits;
// glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &MaxTextureImageUnits);
}
Спасибо заранее за любые советы!
Задача ещё не решена.
Других решений пока нет …