gpt4 book ai didi

c++ - 法线贴图出了可怕的错误

转载 作者:太空狗 更新时间:2023-10-29 19:57:57 25 4
gpt4 key购买 nike

我试图在我的 opengl 应用程序中实现法线贴图,但我无法让它工作。

This是漫反射贴图(我添加了棕色)和 this是法线贴图。

为了获得切线和副切线(在其他地方称为双法线?) vector ,我对网格中的每个三角形运行此函数:

void getTangent(const glm::vec3 &v0, const glm::vec3 &v1, const glm::vec3 &v2,
const glm::vec2 &uv0, const glm::vec2 &uv1, const glm::vec2 &uv2,
std::vector<glm::vec3> &vTangents, std::vector<glm::vec3> &vBiangents)
{
// Edges of the triangle : postion delta
glm::vec3 deltaPos1 = v1-v0;
glm::vec3 deltaPos2 = v2-v0;

// UV delta
glm::vec2 deltaUV1 = uv1-uv0;
glm::vec2 deltaUV2 = uv2-uv0;

float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
glm::vec3 tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y)*r;
glm::vec3 bitangent = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x)*r;

for(int i = 0; i < 3; i++) {
vTangents.push_back(tangent);
vBiangents.push_back(bitangent);
}
}

之后,我调用 glBufferData 将顶点、法线、uvs、切线和双切线上传到 GPU。顶点着色器:

#version 430

uniform mat4 ProjectionMatrix;
uniform mat4 CameraMatrix;
uniform mat4 ModelMatrix;

in vec3 vertex;
in vec3 normal;
in vec2 uv;
in vec3 tangent;
in vec3 bitangent;

out vec2 fsCoords;
out vec3 fsVertex;
out mat3 TBNMatrix;

void main()
{
gl_Position = ProjectionMatrix * CameraMatrix * ModelMatrix * vec4(vertex, 1.0);

fsCoords = uv;
fsVertex = vertex;

TBNMatrix = mat3(tangent, bitangent, normal);
}

片段着色器:

#version 430

uniform sampler2D diffuseMap;
uniform sampler2D normalMap;
uniform mat4 ModelMatrix;
uniform vec3 CameraPosition;

uniform struct Light {
float ambient;
vec3 position;
} light;
uniform float shininess;

in vec2 fsCoords;
in vec3 fsVertex;
in mat3 TBNMatrix;

out vec4 color;

void main()
{
//base color
const vec3 brownColor = vec3(153.0 / 255.0, 102.0 / 255.0, 51.0 / 255.0);
color = vec4(brownColor * (texture(diffuseMap, fsCoords).rgb + 0.25), 1.0);//add a fixed base color (0.25), because its dark as hell

//general vars
vec3 normal = texture(normalMap, fsCoords).rgb * 2.0 - 1.0;
vec3 surfacePos = vec3(ModelMatrix * vec4(fsVertex, 1.0));
vec3 surfaceToLight = normalize(TBNMatrix * (light.position - surfacePos)); //unit vector
vec3 eyePos = TBNMatrix * CameraPosition;

//diffuse
float diffuse = max(0.0, dot(normal, surfaceToLight));

//specular
float specular;
vec3 incidentVector = -surfaceToLight; //unit
vec3 reflectionVector = reflect(incidentVector, normal); //unit vector
vec3 surfaceToCamera = normalize(eyePos - surfacePos); //unit vector
float cosAngle = max(0.0, dot(surfaceToCamera, reflectionVector));
if(diffuse > 0.0)
specular = pow(cosAngle, shininess);

//add lighting to the fragment color (no attenuation for now)
color.rgb *= light.ambient;
color.rgb += diffuse + specular;
}

我得到的图像完全不正确。 (灯位于相机上) horrible results

我在这里做错了什么?

最佳答案

我的赌注是片段着色器中的颜色设置/混合......

  1. 您不止一次设置输出颜色

    如果我没记错的话,某些 gfx 驱动程序会出现大问题,例如行后的所有内容

    color = vec4(brownColor * (texture(diffuseMap, fsCoords).rgb + 0.25), 1.0);//add a fixed base color (0.25), because its dark as hell

    可以被驱动程序删除...

  2. 您正在添加 colorintensities 而不是 color*intensity

    但我可以忽略一些事情。

  3. 首先尝试普通/凹凸着色

    忽略环境光、反射、镜面反射……如果有效,则将其余的一一添加。始终检查着色器的编译日志

懒得进一步分析你的代码,所以我是这样做的:

bump mapping example

左图是空间飞船对象(类似ZXS Elite的毒蛇),固定函数渲染。右侧相同(对象的旋转有点不同),GLSL 着色器和此法线/凹凸贴图

enter image description here

[顶点]

//------------------------------------------------------------------
#version 420 core
//------------------------------------------------------------------
// texture units:
// 0 - texture0 map 2D rgba
// 1 - texture1 map 2D rgba
// 2 - normal map 2D xyz
// 3 - specular map 2D i
// 4 - light map 2D rgb rgb
// 5 - enviroment/skybox cube map 3D rgb

uniform mat4x4 tm_l2g;
uniform mat4x4 tm_l2g_dir;
uniform mat4x4 tm_g2s;

uniform mat4x4 tm_l2s_per;
uniform mat4x4 tm_per;

layout(location=0) in vec3 pos;
layout(location=1) in vec4 col;
layout(location=2) in vec2 txr;
layout(location=3) in vec3 tan;
layout(location=4) in vec3 bin;
layout(location=5) in vec3 nor;

out smooth vec3 pixel_pos;
out smooth vec4 pixel_col;
out smooth vec2 pixel_txr;
//out flat mat3 pixel_TBN;
out smooth mat3 pixel_TBN;
//------------------------------------------------------------------
void main(void)
{
vec4 p;
p.xyz=pos;
p.w=1.0;
p=tm_l2g*p;
pixel_pos=p.xyz;
p=tm_g2s*p;
gl_Position=p;
pixel_col=col;
pixel_txr=txr;
p.xyz=tan.xyz; p.w=1.0; pixel_TBN[0]=normalize((tm_l2g_dir*p).xyz);
p.xyz=bin.xyz; p.w=1.0; pixel_TBN[1]=normalize((tm_l2g_dir*p).xyz);
p.xyz=nor.xyz; p.w=1.0; pixel_TBN[2]=normalize((tm_l2g_dir*p).xyz);
}
//------------------------------------------------------------------

[片段]

//------------------------------------------------------------------
#version 420 core
//------------------------------------------------------------------
in smooth vec3 pixel_pos;
in smooth vec4 pixel_col;
in smooth vec2 pixel_txr;
//in flat mat3 pixel_TBN;
in smooth mat3 pixel_TBN;

uniform sampler2D txr_texture0;
uniform sampler2D txr_texture1;
uniform sampler2D txr_normal;
uniform sampler2D txr_specular;
uniform sampler2D txr_light;
uniform samplerCube txr_skybox;

const int _lights=3;
uniform vec3 light_col0=vec3(0.1,0.1,0.1);
uniform vec3 light_dir[_lights]= // direction to local star in ellipsoid space
{
vec3(0.0,0.0,+1.0),
vec3(0.0,0.0,+1.0),
vec3(0.0,0.0,+1.0),
};
uniform vec3 light_col[_lights]= // local star color * visual intensity
{
vec3(1.0,0.0,0.0),
vec3(0.0,1.0,0.0),
vec3(0.0,0.0,1.0),
};

out layout(location=0) vec4 frag_col;

const vec4 v05=vec4(0.5,0.5,0.5,0.5);
const bool _blend=false;
const bool _reflect=true;
//------------------------------------------------------------------
void main(void)
{
float a=0.0,b,li;
vec4 col,blend0,blend1,specul,skybox;
vec3 normal;
col=(texture2D(txr_normal,pixel_txr.st)-v05)*2.0; // normal/bump maping
// normal=pixel_TBN*col.xyz;
normal=pixel_TBN[0];
blend0=texture(txr_texture0,pixel_txr.st);
blend1=texture(txr_texture1,pixel_txr.st);
specul=texture(txr_specular,pixel_txr.st);
skybox=texture(txr_skybox,normal);

if (_blend)
{
a=blend1.a;
blend0*=1.0-a;
blend1*=a;
blend0+=blend1;
blend0.a=a;
}

col.xyz=light_col0; col.a=0.0; li=0.0; // normal shading (aj s bump mapingom)
for (int i=0;i<_lights;i++)
{
b=dot(light_dir[i],normal.xyz);
if (b<0.0) b=0.0;
// b*=specul.r;
li+=b;
col.xyz+=light_col[i]*b;
}
col*=blend0;
if (li<=0.1)
{
blend0=texture2D(txr_light,pixel_txr.st);
blend0*=1.0-a;
blend0.a=a;
col+=blend0;
}
if (_reflect) col+=skybox*specul.r;
col*=pixel_col;
if (col.r<0.0) col.r=0.0;
if (col.g<0.0) col.g=0.0;
if (col.b<0.0) col.b=0.0;
a=0.0;
if (a<col.r) a=col.r;
if (a<col.g) a=col.g;
if (a<col.b) a=col.b;
if (a>1.0)
{
a=1.0/a;
col.r*=a;
col.g*=a;
col.b*=a;
}
frag_col=col;
}
//------------------------------------------------------------------

这些源代码有点旧,并且针对特定应用混合了不同的东西

所以只从中提取你需要的东西。如果您对变量名称感到困惑,请评论我...

  • tm_代表变换矩阵
  • l2g代表局部坐标系到全局坐标系的变换
  • dir 表示转换仅改变方向(偏移量为 0,0,0)
  • g2s代表global to screen ...
  • per 是透视变换 ...

GLSL编译日志

您必须在编译着色器(不是应用程序!!!)后以编程方式获取其内容。我通过为我使用的每个着色器、程序调用函数 glGetShaderInfoLog 来做到这一点......

[注释]

一些驱动程序优化了“未使用”的变量。正如您在图像中看到的那样,即使片段着色器在代码中包含它,也找不到 txr_texture1 但此应用程序中未使用混合,因此驱动程序自行删除了它......

着色器日志可以向您显示很多信息(语法错误、警告...)

很少有 GLSL IDE 可以使着色器变得简单,但我更喜欢我自己的,因为我可以在其中直接使用目标应用程序代码。我的看起来像这样:

GLSL IDE

每个 txt 窗口都是一个着色器源(顶点、片段...),右下角是剪贴板,左上角是上次编译后的着色器日志,左下角是预览。我设法像 Borland 风格的 IDE 一样编码它(也有键和语法高亮)我看到的其他 IDE 看起来很相似(不同颜色的粗糙 :))无论如何如果你想玩着色器下载这样的应用程序或自己做它会有很大帮助...

TBN 创建也可能存在问题

您应该通过在每个顶点位置绘制彩色线条来目视检查 TBN vector (切线、副法线、法线)是否对应于物体表面。只是为了确定......像这样的事情:

normals

关于c++ - 法线贴图出了可怕的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28525308/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com