-
переделал пример из render monkey скартой нормалей на делфи , но работает не правильно пример на red monkey www.ilianuf.narod.ru/rendermonkey.rar пример на delphi www.ilianuf.narod.ru/delphi.rar помогите найти ошибку или может есть у кого рабочий пример на delphi
-
Смотреть лень, почему вопрос. Как Тангент спейс считаешь? Если я правильно помню, то в РМ тупо задается тенгент и бинормаль в шейдере. Это нифига не правильно.
-
ДА тнгенс нормаль и бинонормаль задаются
а как правильно?как их считать?
-
В статье написано тангенс нормаль и бинонормаль расчитываются заранее и хранятся с картой нормалей
-
Вот как разберешься с расчетом тангент спейса - мне скажи, как делать. ;) С месяц назад копал алгоритмы, вроде все правильно, но нихрена не работает. Временно забил на это дело, до лучших времен.
-
Сам наверно не разберусь
-
На gamedev.ru посмотри. там есть статья. я могу свой исходник кинуть, заодно узнаем, где я косячу: в расчете или в применении.
-
Вот первый алгоритм: 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;
-
Вот второй - переделка с геймдева: 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;
-
На вопрос, как тангент спейс передавать в шейдер. Личноя передаю через текстурные координаты. Мультитекстуринг, которые. Нулевая текстурная коордианата - передает текстурные координаты. Первая - бинормаль Вторая - тангент
-
во блин попал а думал всё просто будет
-
вот рбочий пример www.delphisources.ru/pages/sources/graph/2007_year/igrodel_shaders.html тнгенс нормаль и бинонормаль задаются в программе
-
-
Вот поотрите вроде чёто получилось
www.ilianuf.narod.ru/mapping.rar
прокаментируйте
но тангент спейс не меняется. Как я понял менять его надокогда полигон или камера двигаются или вращаются.
-
Tangent space ("пространство касательных") на то и тангент, что зависит только от объекта, а не его расположения в мире. Менять его надо только при деформации нормалей.
-
"В данном методе освещения следует учесть еще один факт, что при расчете освещения мы никак не учитываем направление нормали самого полигона, то есть при вращении полигона направление нормалей не поменяется. Поэтому, для того чтобы повернуть вектор, мы переносим его в новое пространство, которое называется TangentSpace. "
-
Именно - перенос вектора в Tangent space. Само оно (точнее, вектора его составляющие) расчитано предварительно и зашито в модель. Построение матрицы tangent space-а и перенос всяких внешних векторов в него - уже в шейдере писать надо.
|