计算FragmentShader中的切线空间

时间:2013-06-07 17:07:03

标签: opengl glsl

我想计算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一切正常。 我需要在着色器中为稍后的其他动态部分计算它。

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

目前的情况如下:

enter image description here

1 个答案:

答案 0 :(得分:3)

  

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

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

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

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

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

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