Конференция "Игры" » карта нормалей
 
  • nuflin (25.04.08 13:39) [0]
    переделал пример из render monkey скартой нормалей на делфи , но работает не правильно
    пример на red monkey  www.ilianuf.narod.ru/rendermonkey.rar
    пример на delphi  www.ilianuf.narod.ru/delphi.rar
    помогите найти ошибку
    или может есть у кого рабочий пример на delphi
  • @!!ex © (25.04.08 19:06) [1]
    Смотреть лень, почему вопрос. Как Тангент спейс считаешь? Если я правильно помню, то в РМ тупо задается тенгент и бинормаль в шейдере. Это нифига не правильно.
  • nuflin (25.04.08 20:43) [2]
    ДА тнгенс нормаль и бинонормаль задаются

    а как правильно?как их считать?
  • nuflin (25.04.08 20:50) [3]
    В статье написано тангенс нормаль и бинонормаль расчитываются заранее
    и хранятся с картой нормалей
  • @!!ex © (25.04.08 21:27) [4]
    Вот как разберешься с расчетом тангент спейса - мне скажи, как делать. ;)
    С месяц назад копал алгоритмы, вроде все правильно, но нихрена не работает.
    Временно забил на это дело, до лучших времен.
  • nuflin (25.04.08 21:38) [5]
    Сам наверно не разберусь
  • @!!ex © (25.04.08 21:49) [6]
    На gamedev.ru посмотри. там есть статья. я могу свой исходник кинуть, заодно узнаем, где я косячу: в расчете или в применении.
  • @!!ex © (25.04.08 21:51) [7]
    Вот первый алгоритм:
    Procedure CalcTriangleBasis( const E,F,G:TVector; sE,tE,sF,tF,sG,tG:single;  var tangentX,tangentY:TVector);
    var
     P,Q:TVector;
     s1,t1,s2,t2:single;
     pqMatrix:array[0..1,0..2] of single;
     stMatrix:array[0..1,0..1] of single;
     tbMatrix:array[0..1,0..2] of single;
     temp:single;
    begin
     P := SubVector(F,E);
     Q := SubVector(G,E);
    s1 := sF - sE;
    t1 := tF - tE;
    s2 := sG - sE;
    t2 := tG - tE;
    pqMatrix[0][0] := P.X;
    pqMatrix[0][1] := P.Y;
    pqMatrix[0][2] := P.Z;
    pqMatrix[1][0] := Q.X;
    pqMatrix[1][1] := Q.Y;
    pqMatrix[1][2] := Q.Z;
     temp := 1.0 / ( s1 * t2 - s2 * t1);
    stMatrix[0][0] :=  t2 * temp;
    stMatrix[0][1] := -t1 * temp;
    stMatrix[1][0] := -s2 * temp;
    stMatrix[1][1] :=  s1 * temp;

    tbMatrix[0][0] := stMatrix[0][0] * pqMatrix[0][0] + stMatrix[0][1] * pqMatrix[1][0];
    tbMatrix[0][1] := stMatrix[0][0] * pqMatrix[0][1] + stMatrix[0][1] * pqMatrix[1][1];
    tbMatrix[0][2] := stMatrix[0][0] * pqMatrix[0][2] + stMatrix[0][1] * pqMatrix[1][2];
    tbMatrix[1][0] := stMatrix[1][0] * pqMatrix[0][0] + stMatrix[1][1] * pqMatrix[1][0];
    tbMatrix[1][1] := stMatrix[1][0] * pqMatrix[0][1] + stMatrix[1][1] * pqMatrix[1][1];
    tbMatrix[1][2] := stMatrix[1][0] * pqMatrix[0][2] + stMatrix[1][1] * pqMatrix[1][2];
     tangentX:=NormalizeVector(GetTVector(tbMatrix[0][0], tbMatrix[0][1], tbMatrix[0][2]));
     tangentY:=NormalizeVector(GetTVector(tbMatrix[1][0], tbMatrix[1][1], tbMatrix[1][2]));
    end;

    Function ClosestPointOnLine(const a,b,p:TVector):TVector;
    var
     c,V:TVector;
     d:single;
     t:single;
    begin
     c:=SubVector(p,a);
     V:=SubVector(b,a);
     d:=MagnitudeVector(V);
     V:=NormalizeVector(V);
     t:=DotVector(V, c);
    if t < 0.0 then begin
       Result:=a;
       Exit;
     end;

    if t > d then begin
       Result:=b;
       Exit;
     end;
     V:=ScaleVector(V,t);
     Result:=AddVector(a,V);
    end;

    Function Ortogonalize(const v1,v2:TVector):TVector;
    var
     v2ProjV1:TVector;
    begin
     v2ProjV1:=ClosestPointOnLine( v1, ScaleVector(v1,-1), v2 );
     Result:=NormalizeVector(SubVector(v2,v2ProjV1));
    end;

    Procedure CalculateTangentsAndBinormals(const Mesh:TMesh);
    var
     I,J:integer;
     tangents, binormals:array of TVector;
     ind0,ind1,ind2:integer;
     v1,v2,v3:TVector;
     s1,t1,s2,t2,s3,t3:single;
     t,b:TVector;
     rt,rb:array of TVector;
     count:integer;
     tangentRes,binormalRes:TVector;
    begin
     SetLength(tangents,Mesh.F_Count);
     SetLength(binormals,Mesh.F_Count);
    for  i := 0 to Mesh.F_Count-1 do begin
     ind0 := Mesh.Face[i][0];
     ind1 := Mesh.Face[i][1];
     ind2 := Mesh.Face[i][2];
     v1 := Mesh.Vertex[ind0];
     v2 := Mesh.Vertex[ind1];
     v3 := Mesh.Vertex[ind2];
     s1 := Mesh.TexCoord[ ind0 ].x;
     t1 := Mesh.TexCoord[ ind0 ].y;
     s2 := Mesh.TexCoord[ ind1 ].x;
     t2 := Mesh.TexCoord[ ind1 ].y;
     s3 := Mesh.TexCoord[ ind2 ].x;
     t3 := Mesh.TexCoord[ ind2 ].y;
       CalcTriangleBasis( v1, v2, v3, s1, t1, s2, t2, s3, t3, t, b );
       tangents[i]:=t;
       binormals[i]:=b;
     end;

    // теперь пройдемся по всем вершинам, для каждой из них найдем
    // грани ее содержащие, и запишем все это хозяйство на будущее =)
    for i := 0 to Mesh.V_Count - 1 do begin
       count:=0;
       SetLength(rt,count);
       SetLength(rb,count);
       for j := 0 to Mesh.F_Count - 1 do begin
         if (Mesh.Face[j][0]=i) or (Mesh.Face[j][1]=i) or (Mesh.Face[j][2]=i) then begin
           inc(count);
           SetLength(rt,count);
           SetLength(rb,count);
           rt[count-1]:=tangents[j];
           rb[count-1]:=binormals[j];
         end;
       end;
       tangentRes:=ZeroTVector;
       binormalRes:=ZeroTVector;
     for j := 0 to count-1 do begin
         tangentRes:=AddVector(tangentRes,rt[j]);
         binormalRes:=AddVector(binormalRes,rb[j]);
       end;
       tangentRes:=NormalizeVector(tangentRes);
       binormalRes:=NormalizeVector(binormalRes);

     tangentRes := Ortogonalize( Mesh.Normal[i], tangentRes );
     binormalRes := Ortogonalize( Mesh.Normal[i], binormalRes );

       Mesh.Tangent[i]:=tangentRes;
       Mesh.Binormal[i]:=binormalRes;
     end;
    end;
  • @!!ex © (25.04.08 21:51) [8]
    Вот второй - переделка с геймдева:
    Procedure CalculateTangentSpace(const Mesh:TMesh);
    var
     Index:integer;
     v0, v1, v2:cardinal;
     Q,P:TVector;
     s1,t1,s2,t2:single;
     tmp:single;
     tangent,binormal:TVector;
    begin
     for Index := 0 to Mesh.F_Count - 1 do begin
       v0:=Mesh.Face[Index][0];
       v1:=Mesh.Face[Index][1];
       v2:=Mesh.Face[Index][2];

       Q := SubVector(Mesh.Vertex[v2],Mesh.Vertex[v0]);
       P := SubVector(Mesh.Vertex[v1],Mesh.Vertex[v0]);

       s1 := Mesh.TexCoord[v1].x - Mesh.TexCoord[v0].x;
       t1 := Mesh.TexCoord[v1].y - Mesh.TexCoord[v0].y;
       s2 := Mesh.TexCoord[v2].x - Mesh.TexCoord[v0].x;
       t2 := Mesh.TexCoord[v2].y - Mesh.TexCoord[v0].y;

       tmp := 0.0;
       if abs(s1*t2 - s2*t1) <= 0.0001 then
         tmp := 1.0
       else
         tmp := 1.0/(s1*t2 - s2*t1);

       tangent.x := (t1*Q.x - t2*P.x);
       tangent.y := (t1*Q.y - t2*P.y);
       tangent.z := (t1*Q.z - t2*P.z);
       tangent := ScaleVector(tangent,tmp);
       tangent:=NormalizeVector(tangent);

       binormal.x := (s1*Q.x - s2*P.x);
       binormal.y := (s1*Q.y - s2*P.y);
       binormal.z := (s1*Q.z - s2*P.z);
       binormal := ScaleVector(binormal,tmp);
       binormal:=NormalizeVector(binormal);

       Mesh.Tangent[v0]:=AddVector(Mesh.Tangent[v0],Tangent);
       Mesh.Tangent[v1]:=AddVector(Mesh.Tangent[v1],Tangent);
       Mesh.Tangent[v2]:=AddVector(Mesh.Tangent[v2],Tangent);

       Mesh.Binormal[v0]:=AddVector(Mesh.Binormal[v0],Binormal);
       Mesh.Binormal[v1]:=AddVector(Mesh.Binormal[v1],Binormal);
       Mesh.Binormal[v2]:=AddVector(Mesh.Binormal[v2],Binormal);
     end;

     for Index := 0 to Mesh.V_Count - 1 do begin
       Mesh.Tangent[Index]:=NormalizeVector(Mesh.Tangent[Index]);
       Mesh.Binormal[Index]:=NormalizeVector(Mesh.Binormal[Index]);
     end;

    end;
  • @!!ex © (25.04.08 21:53) [9]
    На вопрос, как тангент спейс передавать в шейдер.
    Личноя  передаю через текстурные координаты. Мультитекстуринг, которые.
    Нулевая текстурная коордианата - передает текстурные координаты.
    Первая - бинормаль
    Вторая - тангент
  • nuflin (25.04.08 22:08) [10]
    во блин попал а думал всё просто будет
  • nuflin (25.04.08 22:14) [11]
    вот рбочий пример
    www.delphisources.ru/pages/sources/graph/2007_year/igrodel_shaders.html
    тнгенс нормаль и бинонормаль задаются в программе
  • XProger © (26.04.08 05:47) [12]
    http://xproger.mirgames.ru/?id=2&page=3#void
    void.Game.Mesh.pas -> procedure TMesh.Load
  • nuflin (30.04.08 11:27) [13]
    Вот поотрите вроде чёто получилось

    www.ilianuf.narod.ru/mapping.rar

    прокаментируйте

    но тангент спейс не меняется. Как я понял менять его надокогда полигон или камера двигаются или вращаются.
  • Asteroid (01.05.08 20:02) [14]
    Tangent space ("пространство касательных") на то и тангент, что зависит только от объекта, а не его расположения в мире. Менять его надо только при деформации нормалей.
  • nuflin (01.05.08 20:31) [15]
    "В данном методе освещения следует учесть еще один факт, что при расчете освещения мы никак не учитываем направление нормали самого полигона, то есть при вращении полигона направление нормалей не поменяется. Поэтому, для того чтобы повернуть вектор, мы переносим его в новое пространство, которое называется TangentSpace. "
  • Asteroid © (08.05.08 06:04) [16]
    Именно - перенос вектора в Tangent space. Само оно (точнее, вектора его составляющие) расчитано предварительно и зашито в модель. Построение матрицы tangent space-а и перенос всяких внешних векторов в него - уже в шейдере писать надо.
 
Конференция "Игры" » карта нормалей
Есть новые Нет новых   [134430   +2][b:0][p:0.001]