C++ 什么';我的法线映射有什么问题?我想是';这是我的切线
编辑:你可能想从“编辑3”开始,因为我已经解决了很多问题 下面是我应用于icosphere的普通立方体贴图的屏幕截图: 使用以下代码生成立方体贴图icosphere的切线C++ 什么';我的法线映射有什么问题?我想是';这是我的切线,c++,opengl,normals,bump-mapping,C++,Opengl,Normals,Bump Mapping,编辑:你可能想从“编辑3”开始,因为我已经解决了很多问题 下面是我应用于icosphere的普通立方体贴图的屏幕截图: 使用以下代码生成立方体贴图icosphere的切线m_索引在std::vector中,将索引转换为std::vector中的m_顶点 std::vector<glm::vec3> storedTan(m_vertices.size(),glm::vec3(0,0,0)); // tangents for(int i = 0; i < m_indices.s
m_索引
在std::vector
中,将索引转换为std::vector
中的m_顶点
std::vector<glm::vec3> storedTan(m_vertices.size(),glm::vec3(0,0,0));
// tangents
for(int i = 0; i < m_indices.size(); i+=3)
{
int i1 = m_indices[i];
int i2 = m_indices[i+1];
int i3 = m_indices[i+2];
VertexData v1 = m_vertices[i1];
VertexData v2 = m_vertices[i2];
VertexData v3 = m_vertices[i3];
glm::vec3 p1 = glm::vec3(v1.position[0],v1.position[1],v1.position[2]);
glm::vec3 p2 = glm::vec3(v2.position[0],v2.position[1],v2.position[2]);
glm::vec3 p3 = glm::vec3(v3.position[0],v3.position[1],v3.position[2]);
glm::vec3 t1 = glm::vec3(v1.tcoords[0],v1.tcoords[1],v1.tcoords[2]);
glm::vec3 t2 = glm::vec3(v2.tcoords[0],v2.tcoords[1],v2.tcoords[2]);
glm::vec3 t3 = glm::vec3(v3.tcoords[0],v3.tcoords[1],v3.tcoords[2]);
std::function<glm::vec2(glm::vec3)> get_uv = [=](glm::vec3 STR)
{
float sc, tc, ma;
float x = std::abs(STR.x);
float y = std::abs(STR.y);
float z = std::abs(STR.z);
if(x > y && x > z)
{
if(STR.x > 0)
{
sc = -STR.z;
tc = -STR.y;
ma = STR.x;
}
else
{
sc = STR.z;
tc = -STR.t;
ma = STR.x;
}
}
else if(y > z)
{
if(STR.y > 0)
{
sc = STR.x;
tc = STR.z;
ma = STR.y;
}
else
{
sc = STR.x;
tc = -STR.z;
ma = STR.y;
}
}
else
{
if(STR.z > 0)
{
sc = STR.x;
tc = -STR.y;
ma = STR.z;
}
else
{
sc = -STR.x;
tc = -STR.y;
ma = STR.z;
}
}
return glm::vec2((sc/std::abs(ma) + 1.0) / 2.0,(tc/std::abs(ma) + 1.0) / 2.0);
};
glm::vec2 uv1 = get_uv(t1);
glm::vec2 uv2 = get_uv(t2);
glm::vec2 uv3 = get_uv(t3);
glm::vec3 edge1 = p2 - p1;
glm::vec3 edge2 = p3 - p1;
glm::vec2 tedge1 = uv2 - uv1;
glm::vec2 tedge2 = uv3 - uv1;
float r = 1.0f / (tedge1.x * tedge2.y - tedge2.x - tedge1.y);
glm::vec3 sdir((tedge2.y * edge1.x - tedge1.y * edge2.x) * r,
(tedge2.y * edge1.y - tedge1.y * edge2.y) * r,
(tedge2.y * edge1.z - tedge1.y * edge2.z) * r);
glm::vec3 tdir((tedge1.x * edge2.x - tedge2.x * edge1.x) * r,
(tedge1.x * edge2.y - tedge2.x * edge1.y) * r,
(tedge1.x * edge2.z - tedge2.x * edge1.z) * r);
m_vertices[i1].tangent[0] += sdir.x;
m_vertices[i1].tangent[1] += sdir.y;
m_vertices[i1].tangent[2] += sdir.z;
m_vertices[i2].tangent[0] += sdir.x;
m_vertices[i2].tangent[1] += sdir.y;
m_vertices[i2].tangent[2] += sdir.z;
m_vertices[i3].tangent[0] += sdir.x;
m_vertices[i3].tangent[1] += sdir.y;
m_vertices[i3].tangent[2] += sdir.z;
storedTan[i1] += sdir;
storedTan[i2] += sdir;
storedTan[i3] += sdir;
}
for(int i = 0; i < m_vertices.size(); ++i)
{
glm::vec3 n = glm::vec3(m_vertices[i].normal[0],m_vertices[i].normal[1],m_vertices[i].normal[2]);
glm::vec3 t = glm::vec3(m_vertices[i].tangent[0],m_vertices[i].tangent[1],m_vertices[i].tangent[2]);
glm::vec3 newT = glm::normalize(t - n * glm::dot(n,t));
m_vertices[i].tangent[0] = newT.x;
m_vertices[i].tangent[1] = newT.y;
m_vertices[i].tangent[2] = newT.z;
m_vertices[i].tangent[3] = (glm::dot(glm::cross(n,t), storedTan[i]) < 0.0f) ? -1.0f : 1.0f;
}
我知道当前的t单词
、位置
和正常
都很好(否则您将看不到上面的屏幕截图)
然后,我的顶点着色器如下所示:
#version 400
layout (location = 0) in vec4 in_position;
layout (location = 1) in vec3 in_normal;
layout (location = 2) in vec3 in_UV;
layout (location = 3) in vec4 in_tangent;
struct PointLight
{
bool active;
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 lightMVP;
uniform PointLight uLight;
smooth out vec3 ex_UV;
out vec3 ex_normal;
out vec3 ex_positionCameraSpace;
out vec3 ex_originalPosition;
out vec3 ex_positionWorldSpace;
out vec4 ex_positionLightSpace;
out vec3 ex_tangent;
out vec3 ex_binormal;
out PointLight ex_light;
void main()
{
gl_Position = projection * view * model * in_position;
ex_UV = in_UV;
ex_normal = mat3(transpose(inverse(view * model))) * in_normal;
ex_positionCameraSpace = vec3(view * model * in_position);
ex_originalPosition = vec3(in_position.xyz);
ex_positionWorldSpace = vec3(model*in_position);
ex_positionLightSpace = lightMVP * model * in_position;
ex_tangent = mat3(transpose(inverse(view * model))) * in_tangent.xyz;
ex_binormal = cross(ex_normal,ex_tangent);
// provide the fragment shader with a light in view space rather than world space
PointLight p = uLight;
p.position = vec3(view * vec4(p.position,1.0));
ex_light = p;
}
#version 400
layout (location = 0) out vec4 color;
struct Material
{
bool useMaps;
samplerCube diffuse;
samplerCube specular;
samplerCube normal;
float shininess;
vec4 color1;
vec4 color2;
};
struct PointLight
{
bool active;
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
uniform Material uMaterial;
smooth in vec3 ex_UV;
in vec3 ex_normal;
in vec3 ex_positionCameraSpace;
in vec3 ex_originalPosition;
in vec3 ex_positionWorldSpace;
in vec4 ex_positionLightSpace;
in vec3 ex_tangent;
in vec3 ex_binormal;
in PointLight ex_light;
/* ******************
Provides a better lookup into a cubemap
******************* */
vec3 fix_cube_lookup(vec3 v, float cube_size)
{
float M = max(max(abs(v.x), abs(v.y)), abs(v.z));
float scale = (cube_size - 1) / cube_size;
if (abs(v.x) != M)
v.x *= scale;
if (abs(v.y) != M)
v.y *= scale;
if (abs(v.z) != M)
v.z *= scale;
return v;
}
/* *********************
Calculates the color when using a point light. Uses shadow map
********************* */
vec3 CalcPointLight(PointLight light, Material mat, vec3 normal, vec3 fragPos, vec3 originalPos, vec3 viewDir)
{
// replace the normal with lookup normal. This is now in tangent space
vec3 textureLookup = fix_cube_lookup(normalize(ex_originalPosition),textureSize(mat.normal,0).x);
normal = texture(mat.normal,textureLookup).rgb;
// the direction the light is in in the light position - fragpos
// light dir and view dir are now in tangent space
vec3 lightDir = transpose(mat3(ex_tangent,ex_binormal,ex_normal)) * normalize(fragPos - light.position);
viewDir = transpose(mat3(ex_tangent,ex_binormal,ex_normal)) * viewDir;
// get the diffuse color
textureLookup = fix_cube_lookup(normalize(ex_originalPosition),textureSize(mat.diffuse,0).x);
vec3 diffuseMat = vec3(0.0);
if(mat.useMaps)
diffuseMat = texture(mat.diffuse,textureLookup).rgb;
else
diffuseMat = mat.color1.rgb;
// get the specular color
textureLookup = fix_cube_lookup(normalize(ex_originalPosition),textureSize(mat.specular,0).x);
vec3 specularMat = vec3(0.0);
if(mat.useMaps)
specularMat = texture(mat.specular,textureLookup).rgb;
else
specularMat = mat.color2.rgb;
// the ambient color is the amount of normal ambient light hitting the diffuse texture
vec3 ambientColor = light.ambient * diffuseMat;
// Diffuse shading
float diffuseFactor = dot(normal, -lightDir);
vec3 diffuseColor = vec3(0,0,0);
vec3 specularColor = vec3(0,0,0);
if(diffuseFactor > 0)
diffuseColor = light.diffuse * diffuseFactor * diffuseMat;
// Specular shading
vec3 reflectDir = normalize(reflect(lightDir, normal));
float specularFactor = pow(dot(viewDir,reflectDir), mat.shininess);
if(specularFactor > 0 && diffuseFactor > 0)
specularColor = light.specular * specularFactor * specularMat;
float lightDistance = length(fragPos - light.position);
float attenuation = light.constant + light.linear * lightDistance + light.quadratic * lightDistance * lightDistance;
return ambientColor + (diffuseColor + specularColor) / attenuation;
}
void main(void)
{
vec3 norm = normalize(ex_normal);
vec3 viewDir = normalize(-ex_positionCameraSpace);
vec3 result = CalcPointLight(ex_light,uMaterial,norm,ex_positionCameraSpace, ex_positionWorldSpace,viewDir);
color = vec4(result,1.0);
}
for(int i = 0; i < 6; ++i)
{
float scale = 15.0;
std::deque<glm::vec4> normalMap(textureSize*textureSize);
for(int x = 0; x < textureSize; ++x)
{
for(int y = 0; y < textureSize; ++y)
{
// center point
int i11 = utils::math::get_1d_array_index_from_2d(x,y,textureSize);
float v11 = cubeFacesHeight[i][i11].r;
// to the left
int i01 = utils::math::get_1d_array_index_from_2d(std::max(x-1,0),y,textureSize);
float v01 = cubeFacesHeight[i][i01].r;
// to the right
int i21 = utils::math::get_1d_array_index_from_2d(std::min(x+1,textureSize-1),y,textureSize);
float v21 = cubeFacesHeight[i][i21].r;
// to the top
int i10 = utils::math::get_1d_array_index_from_2d(x,std::max(y-1,0),textureSize);
float v10 = cubeFacesHeight[i][i10].r;
// and now the bottom
int i12 = utils::math::get_1d_array_index_from_2d(x,std::min(y+1,textureSize-1),textureSize);
float v12 = cubeFacesHeight[i][i12].r;
glm::vec3 S = glm::vec3(1, 0, scale * v21 - scale * v01);
glm::vec3 T = glm::vec3(0, 1, scale * v12 - scale * v10);
glm::vec3 N = (glm::vec3(-S.z,-T.z,1) / std::sqrt(S.z*S.z + T.z*T.z + 1));
N.x = (N.x+1.0)/2.0;
N.y = (N.y+1.0)/2.0;
N.z = (N.z+1.0)/2.0;
normalMap[utils::math::get_1d_array_index_from_2d(x,y,textureSize)] = glm::vec4(N.x,N.y,N.z,v11);
}
}
for(int x = 0; x < textureSize; ++x)
{
for(int y = 0; y < textureSize; ++y)
{
cubeFacesHeight[i][utils::math::get_1d_array_index_from_2d(x,y,textureSize)] = normalMap[utils::math::get_1d_array_index_from_2d(x,y,textureSize)];
}
}
}
最后,我的片段着色器如下所示:
#version 400
layout (location = 0) in vec4 in_position;
layout (location = 1) in vec3 in_normal;
layout (location = 2) in vec3 in_UV;
layout (location = 3) in vec4 in_tangent;
struct PointLight
{
bool active;
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 lightMVP;
uniform PointLight uLight;
smooth out vec3 ex_UV;
out vec3 ex_normal;
out vec3 ex_positionCameraSpace;
out vec3 ex_originalPosition;
out vec3 ex_positionWorldSpace;
out vec4 ex_positionLightSpace;
out vec3 ex_tangent;
out vec3 ex_binormal;
out PointLight ex_light;
void main()
{
gl_Position = projection * view * model * in_position;
ex_UV = in_UV;
ex_normal = mat3(transpose(inverse(view * model))) * in_normal;
ex_positionCameraSpace = vec3(view * model * in_position);
ex_originalPosition = vec3(in_position.xyz);
ex_positionWorldSpace = vec3(model*in_position);
ex_positionLightSpace = lightMVP * model * in_position;
ex_tangent = mat3(transpose(inverse(view * model))) * in_tangent.xyz;
ex_binormal = cross(ex_normal,ex_tangent);
// provide the fragment shader with a light in view space rather than world space
PointLight p = uLight;
p.position = vec3(view * vec4(p.position,1.0));
ex_light = p;
}
#version 400
layout (location = 0) out vec4 color;
struct Material
{
bool useMaps;
samplerCube diffuse;
samplerCube specular;
samplerCube normal;
float shininess;
vec4 color1;
vec4 color2;
};
struct PointLight
{
bool active;
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
uniform Material uMaterial;
smooth in vec3 ex_UV;
in vec3 ex_normal;
in vec3 ex_positionCameraSpace;
in vec3 ex_originalPosition;
in vec3 ex_positionWorldSpace;
in vec4 ex_positionLightSpace;
in vec3 ex_tangent;
in vec3 ex_binormal;
in PointLight ex_light;
/* ******************
Provides a better lookup into a cubemap
******************* */
vec3 fix_cube_lookup(vec3 v, float cube_size)
{
float M = max(max(abs(v.x), abs(v.y)), abs(v.z));
float scale = (cube_size - 1) / cube_size;
if (abs(v.x) != M)
v.x *= scale;
if (abs(v.y) != M)
v.y *= scale;
if (abs(v.z) != M)
v.z *= scale;
return v;
}
/* *********************
Calculates the color when using a point light. Uses shadow map
********************* */
vec3 CalcPointLight(PointLight light, Material mat, vec3 normal, vec3 fragPos, vec3 originalPos, vec3 viewDir)
{
// replace the normal with lookup normal. This is now in tangent space
vec3 textureLookup = fix_cube_lookup(normalize(ex_originalPosition),textureSize(mat.normal,0).x);
normal = texture(mat.normal,textureLookup).rgb;
// the direction the light is in in the light position - fragpos
// light dir and view dir are now in tangent space
vec3 lightDir = transpose(mat3(ex_tangent,ex_binormal,ex_normal)) * normalize(fragPos - light.position);
viewDir = transpose(mat3(ex_tangent,ex_binormal,ex_normal)) * viewDir;
// get the diffuse color
textureLookup = fix_cube_lookup(normalize(ex_originalPosition),textureSize(mat.diffuse,0).x);
vec3 diffuseMat = vec3(0.0);
if(mat.useMaps)
diffuseMat = texture(mat.diffuse,textureLookup).rgb;
else
diffuseMat = mat.color1.rgb;
// get the specular color
textureLookup = fix_cube_lookup(normalize(ex_originalPosition),textureSize(mat.specular,0).x);
vec3 specularMat = vec3(0.0);
if(mat.useMaps)
specularMat = texture(mat.specular,textureLookup).rgb;
else
specularMat = mat.color2.rgb;
// the ambient color is the amount of normal ambient light hitting the diffuse texture
vec3 ambientColor = light.ambient * diffuseMat;
// Diffuse shading
float diffuseFactor = dot(normal, -lightDir);
vec3 diffuseColor = vec3(0,0,0);
vec3 specularColor = vec3(0,0,0);
if(diffuseFactor > 0)
diffuseColor = light.diffuse * diffuseFactor * diffuseMat;
// Specular shading
vec3 reflectDir = normalize(reflect(lightDir, normal));
float specularFactor = pow(dot(viewDir,reflectDir), mat.shininess);
if(specularFactor > 0 && diffuseFactor > 0)
specularColor = light.specular * specularFactor * specularMat;
float lightDistance = length(fragPos - light.position);
float attenuation = light.constant + light.linear * lightDistance + light.quadratic * lightDistance * lightDistance;
return ambientColor + (diffuseColor + specularColor) / attenuation;
}
void main(void)
{
vec3 norm = normalize(ex_normal);
vec3 viewDir = normalize(-ex_positionCameraSpace);
vec3 result = CalcPointLight(ex_light,uMaterial,norm,ex_positionCameraSpace, ex_positionWorldSpace,viewDir);
color = vec4(result,1.0);
}
for(int i = 0; i < 6; ++i)
{
float scale = 15.0;
std::deque<glm::vec4> normalMap(textureSize*textureSize);
for(int x = 0; x < textureSize; ++x)
{
for(int y = 0; y < textureSize; ++y)
{
// center point
int i11 = utils::math::get_1d_array_index_from_2d(x,y,textureSize);
float v11 = cubeFacesHeight[i][i11].r;
// to the left
int i01 = utils::math::get_1d_array_index_from_2d(std::max(x-1,0),y,textureSize);
float v01 = cubeFacesHeight[i][i01].r;
// to the right
int i21 = utils::math::get_1d_array_index_from_2d(std::min(x+1,textureSize-1),y,textureSize);
float v21 = cubeFacesHeight[i][i21].r;
// to the top
int i10 = utils::math::get_1d_array_index_from_2d(x,std::max(y-1,0),textureSize);
float v10 = cubeFacesHeight[i][i10].r;
// and now the bottom
int i12 = utils::math::get_1d_array_index_from_2d(x,std::min(y+1,textureSize-1),textureSize);
float v12 = cubeFacesHeight[i][i12].r;
glm::vec3 S = glm::vec3(1, 0, scale * v21 - scale * v01);
glm::vec3 T = glm::vec3(0, 1, scale * v12 - scale * v10);
glm::vec3 N = (glm::vec3(-S.z,-T.z,1) / std::sqrt(S.z*S.z + T.z*T.z + 1));
N.x = (N.x+1.0)/2.0;
N.y = (N.y+1.0)/2.0;
N.z = (N.z+1.0)/2.0;
normalMap[utils::math::get_1d_array_index_from_2d(x,y,textureSize)] = glm::vec4(N.x,N.y,N.z,v11);
}
}
for(int x = 0; x < textureSize; ++x)
{
for(int y = 0; y < textureSize; ++y)
{
cubeFacesHeight[i][utils::math::get_1d_array_index_from_2d(x,y,textureSize)] = normalMap[utils::math::get_1d_array_index_from_2d(x,y,textureSize)];
}
}
}
据我所知:
或
二维坐标,I:
major axis
direction target sc tc ma
---------- ------------------------------- --- --- ---
+rx TEXTURE_CUBE_MAP_POSITIVE_X_ARB -rz -ry rx
-rx TEXTURE_CUBE_MAP_NEGATIVE_X_ARB +rz -ry rx
+ry TEXTURE_CUBE_MAP_POSITIVE_Y_ARB +rx +rz ry
-ry TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB +rx -rz ry
+rz TEXTURE_CUBE_MAP_POSITIVE_Z_ARB +rx -ry rz
-rz TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB -rx -ry rz
Using the sc, tc, and ma determined by the major axis direction as
specified in the table above, an updated (s,t) is calculated as
follows
s = ( sc/|ma| + 1 ) / 2
t = ( tc/|ma| + 1 ) / 2
This new (s,t) is used to find a texture value in the determined
face's 2D texture image using the rules given in sections 3.8.5
and 3.8.6." ...
编辑
我不知道为什么以前没有,但我已经在几何体着色器中输出法线、切线和双切线,以查看它们面对的方式。我用过
黄色是面法线,绿色是顶点法线。我不确定为什么顶点法线看起来是错误的,它们不会影响任何其他照明,所以这可能只是我的几何体着色器中的一个错误
切线为红色,副法线为蓝色。这些看起来(很难说)像是彼此的前腱,这是正确的,但除此之外,它们没有指向一致的方向。这就是我以前的斑驳图案
我不知道如何解决这个问题
编辑2
我已经解决了显示法线等的问题。现在这个问题已经解决了
结果,我添加了一些阴影以使其更清晰,每种颜色都是不同的立方体面
我改变的另一件事是查找到我的法线贴图。我忘记将范围调整回-1到1(从0到1)
这并不能解决我的问题
令人困惑的是,当我尝试使用纹理中的法线时,我没有得到任何渲染。深度缓冲区中没有任何内容。我已经检查并再次检查纹理是否可以从着色器访问(因此显示应用于球体的纹理的原始屏幕截图)
因为即使我的切线和副法线指向各个方向;我仍然期待着一些东西被展示出来,即使它是错的。但即使是环境色也无法通过。(即使我不使用我的lightDir
和viewdir
也会发生这种情况。如果我忽略顶点法线并查找纹理,我将丢失环境光颜色)
编辑3:最后一个问题
通常情况下,问题的一部分与你认为错误的地方无关。我的问题是我用不同的纹理覆盖了法线贴图的绑定
所以,有了这些,我现在可以看到我的颜色了。用我漂亮性感的凹凸贴图
然而,现在立方体贴图的接缝处出现了一个问题。我不确定这是因为切线的计算还是因为法线贴图的生成方式。我的法线贴图是从每个面的高度贴图独立生成的
这将解释一些接缝的影响,我想,我将修改它,对这些边上的相邻面进行采样,看看会发生什么
我仍然认为生成的切线也会对这些接缝产生不利影响。我的想法是,它们将指向接缝处的相反方向
截图:
编辑4
从EDIT1开始测试时,我使用了一个非常非常低的多边形网格作为我的icosphere。所以我有最小的分部
我想看看我不太完美的法线贴图球体在有很多多边形的情况下是什么样子的。这立刻暴露了这个问题:
如果不清楚的话,从左边开始写的是我的老朋友seam,但下面是看起来像三角形的边
所以在完成了以上所有工作之后,我想我回到了我最初的问题,即切线不正确
仍在寻求阅读本文的人的帮助
编辑4
嗯,那很快。这个网站给了我另一种创建切线的方法。虽然代码似乎有点类似于我在CPU上所做的,但它不会产生那些随机定向的切线,而这些切线是从Edit3生成的边
我现在很接近了。我仍然有接缝,这种生成切线的其他方法似乎增加了它们的“接缝”
编辑5
我现在尝试修改我的普通贴图生成。前面的代码是这样的:
#version 400
layout (location = 0) in vec4 in_position;
layout (location = 1) in vec3 in_normal;
layout (location = 2) in vec3 in_UV;
layout (location = 3) in vec4 in_tangent;
struct PointLight
{
bool active;
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 lightMVP;
uniform PointLight uLight;
smooth out vec3 ex_UV;
out vec3 ex_normal;
out vec3 ex_positionCameraSpace;
out vec3 ex_originalPosition;
out vec3 ex_positionWorldSpace;
out vec4 ex_positionLightSpace;
out vec3 ex_tangent;
out vec3 ex_binormal;
out PointLight ex_light;
void main()
{
gl_Position = projection * view * model * in_position;
ex_UV = in_UV;
ex_normal = mat3(transpose(inverse(view * model))) * in_normal;
ex_positionCameraSpace = vec3(view * model * in_position);
ex_originalPosition = vec3(in_position.xyz);
ex_positionWorldSpace = vec3(model*in_position);
ex_positionLightSpace = lightMVP * model * in_position;
ex_tangent = mat3(transpose(inverse(view * model))) * in_tangent.xyz;
ex_binormal = cross(ex_normal,ex_tangent);
// provide the fragment shader with a light in view space rather than world space
PointLight p = uLight;
p.position = vec3(view * vec4(p.position,1.0));
ex_light = p;
}
#version 400
layout (location = 0) out vec4 color;
struct Material
{
bool useMaps;
samplerCube diffuse;
samplerCube specular;
samplerCube normal;
float shininess;
vec4 color1;
vec4 color2;
};
struct PointLight
{
bool active;
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
uniform Material uMaterial;
smooth in vec3 ex_UV;
in vec3 ex_normal;
in vec3 ex_positionCameraSpace;
in vec3 ex_originalPosition;
in vec3 ex_positionWorldSpace;
in vec4 ex_positionLightSpace;
in vec3 ex_tangent;
in vec3 ex_binormal;
in PointLight ex_light;
/* ******************
Provides a better lookup into a cubemap
******************* */
vec3 fix_cube_lookup(vec3 v, float cube_size)
{
float M = max(max(abs(v.x), abs(v.y)), abs(v.z));
float scale = (cube_size - 1) / cube_size;
if (abs(v.x) != M)
v.x *= scale;
if (abs(v.y) != M)
v.y *= scale;
if (abs(v.z) != M)
v.z *= scale;
return v;
}
/* *********************
Calculates the color when using a point light. Uses shadow map
********************* */
vec3 CalcPointLight(PointLight light, Material mat, vec3 normal, vec3 fragPos, vec3 originalPos, vec3 viewDir)
{
// replace the normal with lookup normal. This is now in tangent space
vec3 textureLookup = fix_cube_lookup(normalize(ex_originalPosition),textureSize(mat.normal,0).x);
normal = texture(mat.normal,textureLookup).rgb;
// the direction the light is in in the light position - fragpos
// light dir and view dir are now in tangent space
vec3 lightDir = transpose(mat3(ex_tangent,ex_binormal,ex_normal)) * normalize(fragPos - light.position);
viewDir = transpose(mat3(ex_tangent,ex_binormal,ex_normal)) * viewDir;
// get the diffuse color
textureLookup = fix_cube_lookup(normalize(ex_originalPosition),textureSize(mat.diffuse,0).x);
vec3 diffuseMat = vec3(0.0);
if(mat.useMaps)
diffuseMat = texture(mat.diffuse,textureLookup).rgb;
else
diffuseMat = mat.color1.rgb;
// get the specular color
textureLookup = fix_cube_lookup(normalize(ex_originalPosition),textureSize(mat.specular,0).x);
vec3 specularMat = vec3(0.0);
if(mat.useMaps)
specularMat = texture(mat.specular,textureLookup).rgb;
else
specularMat = mat.color2.rgb;
// the ambient color is the amount of normal ambient light hitting the diffuse texture
vec3 ambientColor = light.ambient * diffuseMat;
// Diffuse shading
float diffuseFactor = dot(normal, -lightDir);
vec3 diffuseColor = vec3(0,0,0);
vec3 specularColor = vec3(0,0,0);
if(diffuseFactor > 0)
diffuseColor = light.diffuse * diffuseFactor * diffuseMat;
// Specular shading
vec3 reflectDir = normalize(reflect(lightDir, normal));
float specularFactor = pow(dot(viewDir,reflectDir), mat.shininess);
if(specularFactor > 0 && diffuseFactor > 0)
specularColor = light.specular * specularFactor * specularMat;
float lightDistance = length(fragPos - light.position);
float attenuation = light.constant + light.linear * lightDistance + light.quadratic * lightDistance * lightDistance;
return ambientColor + (diffuseColor + specularColor) / attenuation;
}
void main(void)
{
vec3 norm = normalize(ex_normal);
vec3 viewDir = normalize(-ex_positionCameraSpace);
vec3 result = CalcPointLight(ex_light,uMaterial,norm,ex_positionCameraSpace, ex_positionWorldSpace,viewDir);
color = vec4(result,1.0);
}
for(int i = 0; i < 6; ++i)
{
float scale = 15.0;
std::deque<glm::vec4> normalMap(textureSize*textureSize);
for(int x = 0; x < textureSize; ++x)
{
for(int y = 0; y < textureSize; ++y)
{
// center point
int i11 = utils::math::get_1d_array_index_from_2d(x,y,textureSize);
float v11 = cubeFacesHeight[i][i11].r;
// to the left
int i01 = utils::math::get_1d_array_index_from_2d(std::max(x-1,0),y,textureSize);
float v01 = cubeFacesHeight[i][i01].r;
// to the right
int i21 = utils::math::get_1d_array_index_from_2d(std::min(x+1,textureSize-1),y,textureSize);
float v21 = cubeFacesHeight[i][i21].r;
// to the top
int i10 = utils::math::get_1d_array_index_from_2d(x,std::max(y-1,0),textureSize);
float v10 = cubeFacesHeight[i][i10].r;
// and now the bottom
int i12 = utils::math::get_1d_array_index_from_2d(x,std::min(y+1,textureSize-1),textureSize);
float v12 = cubeFacesHeight[i][i12].r;
glm::vec3 S = glm::vec3(1, 0, scale * v21 - scale * v01);
glm::vec3 T = glm::vec3(0, 1, scale * v12 - scale * v10);
glm::vec3 N = (glm::vec3(-S.z,-T.z,1) / std::sqrt(S.z*S.z + T.z*T.z + 1));
N.x = (N.x+1.0)/2.0;
N.y = (N.y+1.0)/2.0;
N.z = (N.z+1.0)/2.0;
normalMap[utils::math::get_1d_array_index_from_2d(x,y,textureSize)] = glm::vec4(N.x,N.y,N.z,v11);
}
}
for(int x = 0; x < textureSize; ++x)
{
for(int y = 0; y < textureSize; ++y)
{
cubeFacesHeight[i][utils::math::get_1d_array_index_from_2d(x,y,textureSize)] = normalMap[utils::math::get_1d_array_index_from_2d(x,y,textureSize)];
}
}
}
所以我现在对广告有点“流血”