Cara menghitung vektor tangen dan bitangent


9

Saya memiliki tekstur yang dimuat dalam three.js, kemudian diteruskan ke shader. Dalam vertex shader saya menghitung yang normal, dan saya simpan ke dalam variabel vektor uv.

<script id="vertexShader" type="x-shader/x-vertex">

                varying vec3 N,P;
                varying vec2 UV;

                void main() {
                    gl_Position= projectionMatrix * modelViewMatrix * vec4(position,1.0);
                    P= position;
                    N= normalMatrix * vec3(normal);
                    UV= uv;
                }
            </script>
            <script id="fragmentShader" type="x-shader/x-fragment">

                varying vec3 N,P;
                varying vec2 UV;
                uniform sampler2D texture;

                void main() {
                    gl_FragColor= texture2D(texture,UV);
                }

            </script>

Bagaimana cara menghitung vektor T dan B?


2
apakah Anda menginginkan algoritma secara umum atau khusus untuk perpustakaan pilihan Anda?
concept3d

Jika saya dapat menghitungnya dengan three.js akan lebih baik.
Ramy Al Zuhouri

Jawaban:


26

Pertama-tama, untuk setiap titik 3D ada vektor garis singgung dan bi-tangen tak terbatas. Gambar di bawah ini menjelaskan mengapa ada jumlah ruang singgung yang tak terbatas untuk setiap titik, garis singgung dan bitangen dapat memiliki arah apa pun di bidang yang ditampilkan.

Jumlah ruang tanget yang tak terbatas untuk setiap simpul

Jadi, inorder untuk menghitung dengan benar ruang tangen 1 yang paling berguna , kami ingin ruang tangen kami disejajarkan sedemikian rupa sehingga sumbu x (garis singgung) sesuai dengan arah u dalam peta bump dan sumbu y (bitangent) sesuai dengan arah v dalam peta benjolan, kita seharusnya sudah memiliki normal dari simpul yang sudah sesuai dengan arah Z dalam ruang singgung.

(1) paling berguna karena pada akhirnya kami ingin vektor normal disampel dari tekstur

Yang terbaik dijelaskan dengan gambar, kami ingin ruang singgung kami selaras seperti yang (u, v)ditunjukkan di bawah ini.

masukkan deskripsi gambar di sini

Sumber gambar meskipun tidak sepenuhnya terkait dengan grafik komputer

Di komputer, pengembang grafis biasanya menggunakan (u,v)juga dikenal sebagai koordinat tekstur. Kami akan menganggap T adalah garis singgung dan B adalah bitangent, dan P0merupakan simpul target kami, yang merupakan bagian dari segitiga (P0,P1,P2).

Pertama ingat apa yang ingin kita lakukan, adalah menghitung tangen dan bitanget yang:

  1. T sejajar dengan u dan B sejajar dengan v.
  2. T dan B terletak pada bidang dengan titik normal (bidang ditunjukkan pada gambar di atas).

Intinya adalah kita sudah mengasumsikan bahwa T dan B terletak pada bidang yang sama dan berkorespondensi dengan U dan V sekarang jika kita dapat mengetahui nilai-nilainya, kita dapat melintasi produk dan vektor ketiga untuk membangun matriks transformasi dari dunia ke ruang singgung.

masukkan deskripsi gambar di sini

Mengingat bahwa kita tahu bahwa setiap vektor 2D dapat ditulis sebagai kombinasi linear dari dua vektor independen 2 dan karena kita sudah memiliki titik-titik segitiga (tepi), ditunjukkan pada gambar di atas. Kita bisa menulis:

E1 = (u1-u0) T + (v1-v0) B

E2 = (u2-u0) T + (v2-v0) B

(2) sebenarnya itulah bagaimana basis matriks diturunkan

Persamaan di atas dapat ditulis dalam bentuk matriks,

| E1x E1y E1z |   | deltaU1 deltaV1 | * | Tx Ty Tz |
| E2x E2y E2z | = | deltaU2 deltaV2 |   | Bx By Bz |

Dengan menyelesaikan persamaan matriks kita dapat menentukan nilai T dan B kita dapat membangun matriks transformasi.

Kode sumber lengkap dalam C ++

#include "Vector4D.h"


struct Triangle
{
    unsigned short  index[3];
};


void CalculateTangentArray(long vertexCount, const Point3D *vertex, const Vector3D *normal,
        const Point2D *texcoord, long triangleCount, const Triangle *triangle, Vector4D *tangent)
{
    Vector3D *tan1 = new Vector3D[vertexCount * 2];
    Vector3D *tan2 = tan1 + vertexCount;
    ZeroMemory(tan1, vertexCount * sizeof(Vector3D) * 2);

    for (long a = 0; a < triangleCount; a++)
    {
        long i1 = triangle->index[0];
        long i2 = triangle->index[1];
        long i3 = triangle->index[2];

        const Point3D& v1 = vertex[i1];
        const Point3D& v2 = vertex[i2];
        const Point3D& v3 = vertex[i3];

        const Point2D& w1 = texcoord[i1];
        const Point2D& w2 = texcoord[i2];
        const Point2D& w3 = texcoord[i3];

        float x1 = v2.x - v1.x;
        float x2 = v3.x - v1.x;
        float y1 = v2.y - v1.y;
        float y2 = v3.y - v1.y;
        float z1 = v2.z - v1.z;
        float z2 = v3.z - v1.z;

        float s1 = w2.x - w1.x;
        float s2 = w3.x - w1.x;
        float t1 = w2.y - w1.y;
        float t2 = w3.y - w1.y;

        float r = 1.0F / (s1 * t2 - s2 * t1);
        Vector3D sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
                (t2 * z1 - t1 * z2) * r);
        Vector3D tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
                (s1 * z2 - s2 * z1) * r);

        tan1[i1] += sdir;
        tan1[i2] += sdir;
        tan1[i3] += sdir;

        tan2[i1] += tdir;
        tan2[i2] += tdir;
        tan2[i3] += tdir;

        triangle++;
    }

    for (long a = 0; a < vertexCount; a++)
    {
        const Vector3D& n = normal[a];
        const Vector3D& t = tan1[a];

        // Gram-Schmidt orthogonalize
        tangent[a] = (t - n * Dot(n, t)).Normalize();

        // Calculate handedness
        tangent[a].w = (Dot(Cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F;
    }

    delete[] tan1;
}

Kode sumber dan derivasi lengkap dapat ditemukan di sini .


Bagaimana jika saya tidak memiliki segitiga? Dalam kasus saya, saya memiliki tekstur yang harus diterapkan pada bola. Bagaimana menyesuaikannya dengan kasing ini?
Ramy Al Zuhouri

@RamyAlZuhouri bukankah sphere build dari segitiga? Anda hanya mengulang simpul seperti dalam kode. Jika bola Anda tidak berbasis segitiga itu cerita yang sama sekali berbeda.
concept3d

Saya menggunakan three.js SphereGeometry (dalam javascript). Mungkin saya harus menyerahkan properti wajah ke shader? Sphere yang saya gambar memiliki 1089 simpul dan 1084 wajah.
Ramy Al Zuhouri

1
Anda menghitung ruang singgung dan meneruskan garis singgung ke shader. Dan Anda harus memiliki akses ke wajah / simpul untuk menghitung ruang singgung.
concept3d

Dalam kasus saya, saya akan memiliki 1084 garis singgung, bagaimana cara memetakan garis singgung dengan simpul?
Ramy Al Zuhouri
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.