{*****************************************TEXTURE WITHOUT SHADING *********************************} {with shading: second part of this file} { TPolygonPerspectiveTextureMappingInfo } procedure TPolygonPerspectiveTextureMappingInfo.SetIntersectionValues( AInter: TIntersectionInfo; AInterX: Single; AWinding, ANumSegment: integer; dy: single; AData: pointer); var info: PPerspectiveTextureInfo; begin AInter.SetValues(AInterX,AWinding,ANumSegment); info := PPerspectiveTextureInfo(AData); TPerspectiveTextureMappingIntersectionInfo(AInter).coordInvZ := dy*info^.InvZSlope + info^.InvZ; TPerspectiveTextureMappingIntersectionInfo(AInter).texCoordDivByZ := info^.TexCoordDivByZ + info^.TexCoordDivByZSlopes*dy; if FLightnesses<>nil then TPerspectiveTextureMappingIntersectionInfo(AInter).lightness := round(info^.lightness + info^.lightnessSlope*dy) else TPerspectiveTextureMappingIntersectionInfo(AInter).lightness := 32768; end; constructor TPolygonPerspectiveTextureMappingInfo.Create( const points: array of TPointF; const pointsZ: array of single; const texCoords: array of TPointF); var i: Integer; lPoints: array of TPointF; nbP: integer; begin if (length(texCoords) <> length(points)) or (length(pointsZ) <> length(points)) then raise Exception.Create('Dimensions mismatch'); setlength(lPoints, length(points)); SetLength(FTexCoords, length(points)); SetLength(FPointsZ, length(points)); nbP := 0; for i := 0 to high(points) do if (i=0) or (points[i].x<>points[i-1].X) or (points[i].y<>points[i-1].y) then begin lPoints[nbP] := points[i]; FTexCoords[nbP] := texCoords[i]; FPointsZ[nbP] := abs(pointsZ[i]); inc(nbP); end; if (nbP>0) and (lPoints[nbP-1].X = lPoints[0].X) and (lPoints[nbP-1].Y = lPoints[0].Y) then dec(NbP); setlength(lPoints, nbP); SetLength(FTexCoords, nbP); SetLength(FPointsZ, nbP); inherited Create(lPoints); end; constructor TPolygonPerspectiveTextureMappingInfo.Create( const points: array of TPointF; const pointsZ: array of single; const texCoords: array of TPointF; const lightnesses: array of word); var i: Integer; lPoints: array of TPointF; nbP: integer; begin if (length(texCoords) <> length(points)) or (length(pointsZ) <> length(points)) or (length(lightnesses) <> length(points)) then raise Exception.Create('Dimensions mismatch'); setlength(lPoints, length(points)); SetLength(FTexCoords, length(points)); SetLength(FPointsZ, length(points)); setLength(FLightnesses, length(points)); nbP := 0; for i := 0 to high(points) do if (i=0) or (points[i].x<>points[i-1].X) or (points[i].y<>points[i-1].y) then begin lPoints[nbP] := points[i]; FTexCoords[nbP] := texCoords[i]; FPointsZ[nbP] := abs(pointsZ[i]); FLightnesses[nbP] := lightnesses[i]; inc(nbP); end; if (nbP>0) and (lPoints[nbP-1].X = lPoints[0].X) and (lPoints[nbP-1].Y = lPoints[0].Y) then dec(NbP); setlength(lPoints, nbP); SetLength(FTexCoords, nbP); SetLength(FPointsZ, nbP); SetLength(FLightnesses, nbP); inherited Create(lPoints); end; {$hints off} function TPolygonPerspectiveTextureMappingInfo.CreateSegmentData(numPt, nextPt: integer; x, y: single): pointer; var info: PPerspectiveTextureInfo; ty,dy: single; CurInvZ,NextInvZ: single; CurTexCoordDivByZ: TPointF; NextTexCoordDivByZ: TPointF; begin New(info); CurInvZ := 1/FPointsZ[numPt]; CurTexCoordDivByZ := FTexCoords[numPt]*CurInvZ; NextInvZ := 1/FPointsZ[nextPt]; NextTexCoordDivByZ := FTexCoords[nextPt]*NextInvZ; ty := FPoints[nextPt].y-FPoints[numPt].y; info^.TexCoordDivByZSlopes := (NextTexCoordDivByZ - CurTexCoordDivByZ)*(1/ty); dy := y-FPoints[numPt].y; info^.TexCoordDivByZ := CurTexCoordDivByZ + info^.TexCoordDivByZSlopes*dy; info^.InvZSlope := (NextInvZ-CurInvZ)/ty; info^.InvZ := CurInvZ+dy*info^.InvZSlope; if FLightnesses <> nil then begin info^.lightnessSlope := (FLightnesses[nextPt] - FLightnesses[numPt])*(1/ty); info^.lightness := FLightnesses[numPt] + info^.lightnessSlope*dy; end else begin info^.lightness := 32768; info^.lightnessSlope := 0; end; Result:= info; end; {$hints on} function TPolygonPerspectiveTextureMappingInfo.CreateIntersectionInfo: TIntersectionInfo; begin Result:= TPerspectiveTextureMappingIntersectionInfo.Create; end; {$hints off} procedure PolygonPerspectiveTextureMappingAliased(bmp: TBGRACustomBitmap; polyInfo: TPolygonPerspectiveTextureMappingInfo; texture: IBGRAScanner; TextureInterpolation: Boolean; NonZeroWinding: boolean; zbuffer: psingle); var inter: array of TIntersectionInfo; nbInter: integer; scanAtFunc: TScanAtFunction; scanAtIntegerFunc: TScanAtIntegerFunction; procedure DrawTextureLineWithoutLight(yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); {$i perspectivescan.inc} procedure DrawTextureLineWithLight(yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); {$define PARAM_USELIGHTING} {$i perspectivescan.inc} procedure DrawTextureLineWithoutLightZBuffer(yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); {$define PARAM_USEZBUFFER} {$i perspectivescan.inc} procedure DrawTextureLineWithLightZBuffer(yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); {$define PARAM_USEZBUFFER} {$define PARAM_USELIGHTING} {$i perspectivescan.inc} var miny, maxy, minx, maxx: integer; yb, i : integer; x1, x2: single; ix1, ix2: integer; begin If not BGRAShapeComputeMinMax(polyInfo,minx,miny,maxx,maxy,bmp) then exit; inter := polyInfo.CreateIntersectionArray; scanAtFunc := @texture.ScanAt; scanAtIntegerFunc := @texture.ScanAtInteger; if zbuffer = nil then begin //vertical scan for yb := miny to maxy do begin //find intersections polyInfo.ComputeAndSort(yb+0.5001,inter,nbInter,NonZeroWinding); for i := 0 to nbinter div 2 - 1 do begin x1 := inter[i + i].interX; x2 := inter[i + i+ 1].interX; if x1 <> x2 then begin ComputeAliasedRowBounds(x1,x2, minx,maxx, ix1,ix2); if ix1 <= ix2 then begin if (TPerspectiveTextureMappingIntersectionInfo(inter[i+i]).lightness = 32768) and (TPerspectiveTextureMappingIntersectionInfo(inter[i+i+1]).lightness = 32768) then DrawTextureLineWithoutLight(yb,ix1,ix2, TPerspectiveTextureMappingIntersectionInfo(inter[i+i]), TPerspectiveTextureMappingIntersectionInfo(inter[i+i+1]), TextureInterpolation) else DrawTextureLineWithLight(yb,ix1,ix2, TPerspectiveTextureMappingIntersectionInfo(inter[i+i]), TPerspectiveTextureMappingIntersectionInfo(inter[i+i+1]), TextureInterpolation); end; end; end; end; end else begin //vertical scan for yb := miny to maxy do begin //find intersections polyInfo.ComputeAndSort(yb+0.5001,inter,nbInter,NonZeroWinding); for i := 0 to nbinter div 2 - 1 do begin x1 := inter[i + i].interX; x2 := inter[i + i+ 1].interX; if x1 <> x2 then begin ComputeAliasedRowBounds(x1,x2, minx,maxx, ix1,ix2); if ix1 <= ix2 then begin if (TPerspectiveTextureMappingIntersectionInfo(inter[i+i]).lightness = 32768) and (TPerspectiveTextureMappingIntersectionInfo(inter[i+i+1]).lightness = 32768) then DrawTextureLineWithoutLightZBuffer(yb,ix1,ix2, TPerspectiveTextureMappingIntersectionInfo(inter[i+i]), TPerspectiveTextureMappingIntersectionInfo(inter[i+i+1]), TextureInterpolation) else DrawTextureLineWithLightZBuffer(yb,ix1,ix2, TPerspectiveTextureMappingIntersectionInfo(inter[i+i]), TPerspectiveTextureMappingIntersectionInfo(inter[i+i+1]), TextureInterpolation); end; end; end; end; end; polyInfo.FreeIntersectionArray(inter); bmp.InvalidateBitmap; end; {$hints on} procedure PolygonPerspectiveTextureMappingAliased(bmp: TBGRACustomBitmap; const points: array of TPointF; const pointsZ: array of single; texture: IBGRAScanner; const texCoords: array of TPointF; TextureInterpolation: Boolean; NonZeroWinding: boolean; zbuffer: psingle); var polyInfo: TPolygonPerspectiveTextureMappingInfo; begin polyInfo := TPolygonPerspectiveTextureMappingInfo.Create(points,pointsZ,texCoords); PolygonPerspectiveTextureMappingAliased(bmp,polyInfo,texture,TextureInterpolation, NonZeroWinding, zbuffer); polyInfo.Free; end; procedure PolygonPerspectiveTextureMappingAliasedWithLightness( bmp: TBGRACustomBitmap; const points: array of TPointF; const pointsZ: array of single; texture: IBGRAScanner; const texCoords: array of TPointF; TextureInterpolation: Boolean; lightnesses: array of word; NonZeroWinding: boolean; zbuffer: psingle); var polyInfo: TPolygonPerspectiveTextureMappingInfo; begin polyInfo := TPolygonPerspectiveTextureMappingInfo.Create(points,pointsZ,texCoords,lightnesses); PolygonPerspectiveTextureMappingAliased(bmp,polyInfo,texture,TextureInterpolation, NonZeroWinding, zbuffer); polyInfo.Free; end; {****************************************** WITH SHADING ******************************************} {$hints off} procedure PolygonPerspectiveMappingShaderAliased_DrawTextureLine(bmp: TBGRACustomBitmap; ShaderFunction: TShaderFunction3D; ShaderContext: PBasicLightingContext; solidColor: TBGRAPixel; scanAtFunc: TScanAtFunction; scanAtIntegerFunc: TScanAtIntegerFunction; zbuffer: psingle; yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); {$define PARAM_USESHADER} {$i perspectivescan.inc} procedure PolygonPerspectiveMappingShaderAliased_DrawSolidColorLine(bmp: TBGRACustomBitmap; ShaderFunction: TShaderFunction3D; ShaderContext: PBasicLightingContext; solidColor: TBGRAPixel; scanAtFunc: TScanAtFunction; scanAtIntegerFunc: TScanAtIntegerFunction; zbuffer: psingle; yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); {$define PARAM_USESOLIDCOLOR} {$define PARAM_USESHADER} {$i perspectivescan.inc} procedure PolygonPerspectiveMappingShaderAliased_DrawTextureLineZBuffer(bmp: TBGRACustomBitmap; ShaderFunction: TShaderFunction3D; ShaderContext: PBasicLightingContext; solidColor: TBGRAPixel; scanAtFunc: TScanAtFunction; scanAtIntegerFunc: TScanAtIntegerFunction; zbuffer: psingle; yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); {$define PARAM_USESHADER} {$define PARAM_USEZBUFFER} {$i perspectivescan.inc} procedure PolygonPerspectiveMappingShaderAliased_DrawSolidColorLineZBuffer(bmp: TBGRACustomBitmap; ShaderFunction: TShaderFunction3D; ShaderContext: PBasicLightingContext; solidColor: TBGRAPixel; scanAtFunc: TScanAtFunction; scanAtIntegerFunc: TScanAtIntegerFunction; zbuffer: psingle; yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); {$define PARAM_USESOLIDCOLOR} {$define PARAM_USESHADER} {$define PARAM_USEZBUFFER} {$i perspectivescan.inc} procedure PolygonPerspectiveMappingAliased_DrawTextureLine(bmp: TBGRACustomBitmap; ShaderFunction: TShaderFunction3D; ShaderContext: PBasicLightingContext; solidColor: TBGRAPixel; scanAtFunc: TScanAtFunction; scanAtIntegerFunc: TScanAtIntegerFunction; zbuffer: psingle; yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); {$i perspectivescan.inc} procedure PolygonPerspectiveMappingAliased_DrawSolidColorLine(bmp: TBGRACustomBitmap; ShaderFunction: TShaderFunction3D; ShaderContext: PBasicLightingContext; solidColor: TBGRAPixel; scanAtFunc: TScanAtFunction; scanAtIntegerFunc: TScanAtIntegerFunction; zbuffer: psingle; yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); {$define PARAM_USESOLIDCOLOR} {$i perspectivescan.inc} procedure PolygonPerspectiveMappingAliased_DrawTextureLineZBuffer(bmp: TBGRACustomBitmap; ShaderFunction: TShaderFunction3D; ShaderContext: PBasicLightingContext; solidColor: TBGRAPixel; scanAtFunc: TScanAtFunction; scanAtIntegerFunc: TScanAtIntegerFunction; zbuffer: psingle; yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); {$define PARAM_USEZBUFFER} {$i perspectivescan.inc} procedure PolygonPerspectiveMappingAliased_DrawSolidColorLineZBuffer(bmp: TBGRACustomBitmap; ShaderFunction: TShaderFunction3D; ShaderContext: PBasicLightingContext; solidColor: TBGRAPixel; scanAtFunc: TScanAtFunction; scanAtIntegerFunc: TScanAtIntegerFunction; zbuffer: psingle; yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); {$define PARAM_USESOLIDCOLOR} {$define PARAM_USEZBUFFER} {$i perspectivescan.inc} {$hints on} {$hints off} procedure PolygonPerspectiveMappingShaderAliased(bmp: TBGRACustomBitmap; polyInfo: TPolygonPerspectiveMappingShaderInfo; texture: IBGRAScanner; TextureInterpolation: Boolean; ShaderFunction: TShaderFunction3D; NonZeroWinding: boolean; solidColor: TBGRAPixel; zbuffer: psingle; ShaderContext: PBasicLightingContext); var inter: array of TIntersectionInfo; nbInter: integer; scanAtFunc: TScanAtFunction; scanAtIntegerFunc: TScanAtIntegerFunction; drawFunc : procedure(bmp: TBGRACustomBitmap; ShaderFunction: TShaderFunction3D; ShaderContext: PBasicLightingContext; solidColor: TBGRAPixel; scanAtFunc: TScanAtFunction; scanAtIntegerFunc: TScanAtIntegerFunction; zbuffer: psingle; yb: integer; ix1: integer; ix2: integer; info1, info2 : TPerspectiveTextureMappingIntersectionInfo; WithInterpolation: boolean); var miny, maxy, minx, maxx: integer; yb, i : integer; x1, x2: single; ix1, ix2: integer; shaderContextMem: TMemoryBlockAlign128; shaderContextPtr: PBasicLightingContext; inter1,inter2: TPerspectiveTextureMappingIntersectionInfo; begin If not BGRAShapeComputeMinMax(polyInfo,minx,miny,maxx,maxy,bmp) then exit; inter := polyInfo.CreateIntersectionArray; if texture <> nil then begin scanAtFunc := @texture.ScanAt; scanAtIntegerFunc := @texture.ScanAtInteger; end else begin scanAtFunc := nil; scanAtIntegerFunc := nil; end; shaderContextMem := nil; shaderContextPtr := nil; if ShaderFunction <> nil then begin if ShaderContext = nil then begin shaderContextMem := TMemoryBlockAlign128.Create(sizeof(TBasicLightingContext)); shaderContextPtr := PBasicLightingContext( shaderContextMem.Data); end else shaderContextPtr := shaderContext; if texture <> nil then begin if zbuffer = nil then drawFunc := @PolygonPerspectiveMappingShaderAliased_DrawTextureLine else drawFunc := @PolygonPerspectiveMappingShaderAliased_DrawTextureLineZBuffer; end else begin if zbuffer = nil then drawFunc := @PolygonPerspectiveMappingShaderAliased_DrawSolidColorLine else drawFunc := @PolygonPerspectiveMappingShaderAliased_DrawSolidColorLineZBuffer; end; end else begin if texture <> nil then begin if zbuffer = nil then drawFunc := @PolygonPerspectiveMappingAliased_DrawTextureLine else drawFunc := @PolygonPerspectiveMappingAliased_DrawTextureLineZBuffer; end else begin if zbuffer = nil then drawFunc := @PolygonPerspectiveMappingAliased_DrawSolidColorLine else drawFunc := @PolygonPerspectiveMappingAliased_DrawSolidColorLineZBuffer; end; end; //vertical scan for yb := miny to maxy do begin //find intersections polyInfo.ComputeAndSort(yb+0.5001,inter,nbInter,NonZeroWinding); for i := 0 to nbinter div 2 - 1 do begin inter1 := TPerspectiveTextureMappingIntersectionInfo(inter[i+i]); inter2 := TPerspectiveTextureMappingIntersectionInfo(inter[i+i+1]); x1 := inter1.interX; x2 := inter2.interX; if x1 <> x2 then begin ComputeAliasedRowBounds(x1,x2, minx,maxx, ix1,ix2); if ix1 <= ix2 then begin drawFunc(bmp,ShaderFunction,shaderContextPtr, solidColor,scanAtFunc,scanAtIntegerFunc,zbuffer, yb,ix1,ix2, inter1,inter2,TextureInterpolation); end; end; end; end; polyInfo.FreeIntersectionArray(inter); bmp.InvalidateBitmap; shaderContextMem.Free; end; {$hints on} procedure PolygonPerspectiveMappingShaderAliased(bmp: TBGRACustomBitmap; const points: array of TPointF; const points3D: array of TPoint3D; const normals: array of TPoint3D; texture: IBGRAScanner; const texCoords: array of TPointF; TextureInterpolation: Boolean; ShaderFunction: TShaderFunction3D; NonZeroWinding: boolean; solidColor: TBGRAPixel; zbuffer: psingle; ShaderContext: PBasicLightingContext); var polyInfo: TPolygonPerspectiveMappingShaderInfo; begin polyInfo := TPolygonPerspectiveMappingShaderInfo.Create(points,points3D,normals,texCoords); PolygonPerspectiveMappingShaderAliased(bmp,polyInfo,texture,TextureInterpolation, ShaderFunction, NonZeroWinding, solidColor, zbuffer, ShaderContext); polyInfo.Free; end; procedure PolygonPerspectiveMappingShaderAliased(bmp: TBGRACustomBitmap; const points: array of TPointF; const points3D: array of TPoint3D_128; const normals: array of TPoint3D_128; texture: IBGRAScanner; const texCoords: array of TPointF; TextureInterpolation: Boolean; ShaderFunction: TShaderFunction3D; NonZeroWinding: boolean; solidColor: TBGRAPixel; zbuffer: psingle; ShaderContext: PBasicLightingContext); var polyInfo: TPolygonPerspectiveMappingShaderInfo; begin polyInfo := TPolygonPerspectiveMappingShaderInfo.Create(points,points3D,normals,texCoords); PolygonPerspectiveMappingShaderAliased(bmp,polyInfo,texture,TextureInterpolation, ShaderFunction, NonZeroWinding, solidColor, zbuffer, ShaderContext); polyInfo.Free; end; { TPolygonPerspectiveMappingShaderInfo } procedure TPolygonPerspectiveMappingShaderInfo.SetIntersectionValues( AInter: TIntersectionInfo; AInterX: Single; AWinding, ANumSegment: integer; dy: single; AData: pointer); var info : PPerspectiveTextureInfo; begin AInter.SetValues(AInterX,AWinding,ANumSegment); info := PPerspectiveTextureInfo(AData); TPerspectiveTextureMappingIntersectionInfo(AInter).coordInvZ := dy*info^.InvZSlope + info^.InvZ; TPerspectiveTextureMappingIntersectionInfo(AInter).texCoordDivByZ := info^.TexCoordDivByZ + info^.TexCoordDivByZSlopes*dy; TPerspectiveTextureMappingIntersectionInfo(AInter).Position3D := info^.Position3D + info^.Position3DSlope*dy; TPerspectiveTextureMappingIntersectionInfo(AInter).Normal3D := info^.Normal3D + info^.Normal3DSlope*dy; end; constructor TPolygonPerspectiveMappingShaderInfo.Create( const points: array of TPointF; const points3D: array of TPoint3D; const normals: array of TPoint3D; const texCoords: array of TPointF); var i: Integer; lPoints: array of TPointF; nbP: integer; begin if (length(texCoords) <> length(points)) or (length(points3D) <> length(points)) or (length(normals) <> length(points)) then raise Exception.Create('Dimensions mismatch'); setlength(lPoints, length(points)); SetLength(FTexCoords, length(points)); SetLength(FPositions3D, length(points)); SetLength(FNormals3D, length(points)); nbP := 0; for i := 0 to high(points) do if (i=0) or (points[i]<>points[i-1]) then begin lPoints[nbP] := points[i]; FTexCoords[nbP] := texCoords[i]; FPositions3D[nbP] := Point3D_128(points3D[i]); FNormals3D[nbP] := Point3D_128(normals[i]); inc(nbP); end; if (nbP>0) and (lPoints[nbP-1].X = lPoints[0].X) and (lPoints[nbP-1].Y = lPoints[0].Y) then dec(NbP); setlength(lPoints, nbP); SetLength(FTexCoords, nbP); SetLength(FPositions3D, nbP); SetLength(FNormals3D, nbP); inherited Create(lPoints); end; constructor TPolygonPerspectiveMappingShaderInfo.Create( const points: array of TPointF; const points3D: array of TPoint3D_128; const normals: array of TPoint3D_128; const texCoords: array of TPointF); var i: Integer; lPoints: array of TPointF; nbP: integer; begin if (length(texCoords) <> length(points)) or (length(points3D) <> length(points)) or (length(normals) <> length(points)) then raise Exception.Create('Dimensions mismatch'); setlength(lPoints, length(points)); SetLength(FTexCoords, length(points)); SetLength(FPositions3D, length(points)); SetLength(FNormals3D, length(points)); nbP := 0; for i := 0 to high(points) do if (i=0) or (points[i]<>points[i-1]) then begin lPoints[nbP] := points[i]; FTexCoords[nbP] := texCoords[i]; FPositions3D[nbP] := points3D[i]; FNormals3D[nbP] := normals[i]; inc(nbP); end; if (nbP>0) and (lPoints[nbP-1].X = lPoints[0].X) and (lPoints[nbP-1].Y = lPoints[0].Y) then dec(NbP); setlength(lPoints, nbP); SetLength(FTexCoords, nbP); SetLength(FPositions3D, nbP); SetLength(FNormals3D, nbP); inherited Create(lPoints); end; {$hints off} function TPolygonPerspectiveMappingShaderInfo.CreateSegmentData(numPt, nextPt: integer; x, y: single): pointer; var info: PPerspectiveTextureInfo; ty,dy: single; CurInvZ,NextInvZ: single; CurTexCoordDivByZ: TPointF; NextTexCoordDivByZ: TPointF; Cur3DDivByZ,Next3DDivByZ: TPoint3D_128; begin New(info); CurInvZ := FPositions3D[numPt].z; if CurInvZ = 0 then CurInvZ := 1 else CurInvZ := 1/CurInvZ; CurTexCoordDivByZ := FTexCoords[numPt]*CurInvZ; NextInvZ := FPositions3D[nextPt].z; if NextInvZ = 0 then NextInvZ := 1 else NextInvZ := 1/NextInvZ; NextTexCoordDivByZ := FTexCoords[nextPt]*NextInvZ; ty := FPoints[nextPt].y-FPoints[numPt].y; info^.TexCoordDivByZSlopes := (NextTexCoordDivByZ - CurTexCoordDivByZ)*(1/ty); dy := y-FPoints[numPt].y; info^.TexCoordDivByZ := CurTexCoordDivByZ + info^.TexCoordDivByZSlopes*dy; info^.InvZSlope := (NextInvZ-CurInvZ)/ty; info^.InvZ := CurInvZ+dy*info^.InvZSlope; Cur3DDivByZ := FPositions3D[numPt]*CurInvZ; Next3DDivByZ := FPositions3D[nextPt]*NextInvZ; info^.Position3DSlope := (Next3DDivByZ - Cur3DDivByZ)*(1/ty); info^.Position3D := Cur3DDivByZ + info^.Position3DSlope*dy; Cur3DDivByZ := FNormals3D[numPt]*CurInvZ; Next3DDivByZ := FNormals3D[nextPt]*NextInvZ; info^.Normal3DSlope := (Next3DDivByZ - Cur3DDivByZ)*(1/ty); info^.Normal3D := Cur3DDivByZ + info^.Normal3DSlope*dy; Result:= info; end; {$hints on} function TPolygonPerspectiveMappingShaderInfo.CreateIntersectionInfo: TIntersectionInfo; begin Result:= TPerspectiveTextureMappingIntersectionInfo.Create; end;