2

我想计算 GLSL 中的切线空间。

这是我的代码中的重要部分:

// variables passed from vertex to fragment program //
in vec3 vertexNormal;
in vec2 textureCoord;
in vec3 lightPosition;
in vec3 vertexPos;
in mat4 modelView;
in mat4 viewMatrix;

// TODO: textures for color and normals //
uniform sampler2D normal;
uniform sampler2D texture;


// this defines the fragment output //
out vec4 color;

void main() {
 // ###### TANGENT SPACE STUFF ############
    vec4 position_eye = modelView * vec4(vertexPos,1.0);
    vec3 q0 = dFdx(position_eye.xyz);
    vec3 q1 = dFdy(position_eye.xyz);
    vec2 st0 = dFdx(textureCoord.st);
    vec2 st1 = dFdy(textureCoord.st);

    float Sx = ( q0.x * st1.t - q1.x * st0.t) / (st1.t * st0.s - st0.t * st1.s);
    float Tx = (-q0.x * st1.s + q1.x * st0.s) / (st1.t * st0.s - st0.t * st1.s);

    q0.x = st0.s * Sx + st0.t * Tx;
    q1.x = st1.s * Sx + st1.t * Tx;

    vec3 S = normalize( q0 * st1.t - q1 * st0.t);
    vec3 T = normalize(-q0 * st1.s + q1 * st0.s);

    vec3 n = texture2D(normal,textureCoord).xyz;
    n = smoothstep(-1,1,n);

    mat3 tbn = (mat3(S,T,n));

 // #######################################

n = tbn * n; // transfer the read normal to worldSpace;


vec3 eyeDir = - (modelView * vec4(vertexPos,1.0)).xyz;

vec3 lightDir =   (modelView * vec4(lightPosition.xyz, 1.0)).xyz;

在此代码之后有一个 phong 着色,它将与纹理混合。在没有 normalMapping 的情况下将着色器应用于法线纹理一切正常。我需要在着色器中为以后的其他动态部分计算这个。

有人可以告诉我出了什么问题吗?

这是它目前的样子:

在此处输入图像描述

4

1 回答 1

2

有人可以告诉我出了什么问题吗?

您正在尝试在着色器中计算切线空间基矩阵;这就是问题所在。你实际上不能那样做。

dFdx/y计算给定值的变化率,局部在屏幕空间中,在图元的表面上。换句话说,它计算给定值对原语的导数。您的输入值是线性插值的。

一条线的导数是一个常数线ar 插值产生线ar 结果。因此,每个基元的每个片段都将获得相同的输入/输出导数。因此,每个片段都将计算相同的S 和 T 值,因为它们完全基于导数。

这就是为什么你得到一个多面的表面:三个矩阵分量中的两个在三角形的表面上是相同的。

您的计算不起作用,因为它不起作用。您将不得不做其他人所做的事情:离线计算 NBT 矩阵并将它们作为每个顶点的属性传递。或者使用网格的一些已知属性来计算它们。但是这个?这是行不通的。

于 2013-06-07T17:26:11.117 回答