Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

13.07.2021, 19:14

Negative Texture Coordinaten in positive umwandeln

moin,

ich habe ein Modell wo die Texturkoordinaten teils negativ sind.

ich schreibe einen software renderer mit einem rastarizer.

wie wandele ich die u's un v's von negativen in positive coordinaten.
ich hoffe in dem modell ist repeat gemeint

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

13.07.2021, 22:36

Bevor du rasterst, sämtliche x-Texturkoordinaten desselben Dreiecks (oder was auch immer du zeichnest) gleichermaßen um Vielfache von 1 erhöhen (Minimum von floor aller Werte subtrahieren), so dass keine negativen Werte mehr vorkommen. Gleiches für y. Wichtig ist, dass du das für alle Vertices machst, die an dem jeweiligen Dreieck (oder was auch immer) beteiligt sind - egal ob sie negative Texturkoordinaten haben oder nicht - denn sonst verfälschst du das Ergebnis.

Jonathan

Community-Fossil

  • Private Nachricht senden

3

14.07.2021, 18:30

Wichtig ist, dass du das für alle Vertices machst, die an dem jeweiligen Dreieck (oder was auch immer) beteiligt sind - egal ob sie negative Texturkoordinaten haben oder nicht - denn sonst verfälschst du das Ergebnis.

Warum?

Letztendlich ist doch nur für Koordinaten zwischen 0 und 1 klar, wo man sie in der Textur findet. Wenn man jetzt auf alles 1 addiert hat man bei positiven Werten danach Werte größer 1 die erstmal genau so problematisch sind, wie Werte kleiner 0.

Wenn der Repeat-Mode genutzt wird kann man auch nicht die Texturkoordianten auf Vertex-Ebene normalisieren, sondern muss das pro Pixel/Fragment tun. Denn wenn man alles gleich auf 0..1 umrechnet wäre es ja unmöglich, eine Textur innerhalb eines Dreiecks 10 mal zu wiederholen.

D.h. muss man vermutlich für jeden Pixel die Texturkoordinaten interpolieren und dann erst normalisieren (und sich nebenher überlegen, wie man den Texturfilter umsetzt). Zum Normalisieren sollte dann ein (x - floor(x)) ausreichen. Dadurch wird aus 2.6 ein 0.6 und aus -2.6 ein 0.4, was zumindest im Repeat-Mode korrekt ist.
Lieber dumm fragen, als dumm bleiben!

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

4

14.07.2021, 18:37

Wichtig ist, dass du das für alle Vertices machst, die an dem jeweiligen Dreieck (oder was auch immer) beteiligt sind - egal ob sie negative Texturkoordinaten haben oder nicht - denn sonst verfälschst du das Ergebnis.

Warum?

Einfaches Beispiel: Ein Dreieck mit starkem Tiling. Ein Vertex hat Texturkoordinaten (-1000, -1000), die beiden anderen haben (1, 0) und (0, 1). Die Textur wird also 1000x in jede Richtung gekachelt.
Wenn er jetzt nur den einen Vertex anpasst und die Texturkoordinaten nach (0, 0) ändert, was x - floor(x) entspricht, dann hat er plötzlich gar kein Tiling mehr.
Man muss also x - floor(min(alle_x)) machen, und zwar für alle Vertices. Gleiches mit y.

Wenn der Repeat-Mode genutzt wird kann man auch nicht die Texturkoordianten auf Vertex-Ebene normalisieren, sondern muss das pro Pixel/Fragment tun. Denn wenn man alles gleich auf 0..1 umrechnet wäre es ja unmöglich, eine Textur innerhalb eines Dreiecks 10 mal zu wiederholen.

D.h. muss man vermutlich für jeden Pixel die Texturkoordinaten interpolieren und dann erst normalisieren (und sich nebenher überlegen, wie man den Texturfilter umsetzt). Zum Normalisieren sollte dann ein (x - floor(x)) ausreichen. Dadurch wird aus 2.6 ein 0.6 und aus -2.6 ein 0.4, was zumindest im Repeat-Mode korrekt ist.

Komplett normalisieren kann man vor dem Interpolieren nicht, das stimmt. Es ging hier ja auch nur darum, dass man negative Koordinaten loswird. Und das kann man schon machen, so wie ich es beschrieben habe. Du verschiebst damit quasi das komplette Dreieck in den Texturkoordinaten gerade so weit, dass kein Vertex mehr ins Negative ragt. Dann spart man sich das vermutlich teure x - floor(x) pro Pixel, weil man schon weiß, dass die Koordinaten nie negativ sein können.

5

14.07.2021, 18:38

-> um Vielfache von 1 erhöhen (Minimum von floor aller Werte subtrahieren)

leider ist mir diese Erklärung zu knapp, habe das nicht verstanden :(

soll ich alle vertex durchgehen. min von den U's rausfinden. dann floor(minU)-u machen?

kanst du bitte ein Codebeispiel bringen

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

6

14.07.2021, 18:40

soll ich alle vertex durchgehen. min von den U's rausfinden. dann floor(minU)-u machen?

Ja, genau. minU = Minimum der u-Koordinaten aller drei Vertices, die das Dreieck ausmachen. Gleichermaßen gehst du mit v vor. Das machst du, bevor du anfängst das Dreieck zu rastern.

7

14.07.2021, 18:51

vor dem zeichnen pro poly:

Quellcode

1
2
3
4
5
6
7
8
9
minU:=poly.v[0].tu;
for x:=1 to poly.numVertex-1 do begin
  minU:=min(minU,poly.v[x].tu);
end;

minV:=poly.v[0].tv;
for x:=1 to poly.numVertex-1 do begin
  minV:=min(minV,poly.v[x].tv);
end;



pro pixel im rasterizer:

Quellcode

1
2
3
4
5
u1:=floor(minU)-u;
v1:=floor(minV)-v;

tx:=round((u1*invW)*(texture.width-1)); 
ty:=round((v1*invW)*(texture.height-1));




das funkt immer noch nicht

8

14.07.2021, 19:15

bei dem oben gennanten verfahren ist floor(minU) immer -1

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

9

14.07.2021, 19:28

Pro Pixel immer wieder floor(minU) und floor(minV) zu berechnen ist ineffizient. Mach das nur ein einziges mal vor dem Zeichnen und merk dir das in Variablen floorMinU und floorMinV.
Und dann muss es pro Pixel u - floorMinU und v - floorMinV heißen (du hast bei der Differenz die Terme andersherum und kriegst daher immer negative Werte).

10

14.07.2021, 19:37

hier mein rasterizer:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
procedure v3dRasterizeCorrect(poly:v3dPoly; texture:gfxImage; var vp:v3dViewPort);
procedure SetSide(b,e:v3dVertex; var side:v3dScreenSide); 
var 
    len:single; 
    startoffset,endoffset:single;
    offsetstep:single;
    y:longint;
    subpix:single;
    Z,Zstep:single;
    W,Wstep:single; 
    U,Ustep:single; 
    V,Vstep:single;  
begin

    len:=e.v.y - b.v.y;

    if len<=0 then begin
        side[ceil(b.v.y)].offset:=ceil(b.v.y*vp.screen.width + b.v.x);
        exit;
    end;

    startoffset:=b.v.y*vp.screen.width + b.v.x;
    endoffset:=e.v.y*vp.screen.width + e.v.x;

    offsetstep:= (endoffset - startoffset) / len;

    subpix:=ceil(b.v.y) - b.v.y;

    startoffset:=startoffset + offsetstep*subpix;

    


    Zstep:=(e.v.z - b.v.z) / len; 

    Ustep:=(e.tu - b.tu) / len; 
    Vstep:=(e.tv - b.tv) / len; 

    Wstep:=(e.v.w - b.v.w) / len;
 

    Z:=b.v.z + Zstep*subpix; 

    U:=b.tu + Ustep*subpix; 
    V:=b.tv + Vstep*subpix; 

    W:=b.v.w + Wstep*subpix;


    for y:=ceil(b.v.y) to ceil(e.v.y)-1 do begin

        side[y].offset:=ceil(startoffset);
        side[y].z:=Z;
        side[y].w:=W;
        side[y].u:=U; 
        side[y].v:=V; 

        side[y].subpix:=ceil(b.v.y) - b.v.y;


        startoffset:=startoffset+offsetstep;

        z:=z+Zstep;
        w:=w+Wstep;

        u:=u+Ustep;
        v:=v+Vstep; 

    end;


end; 


var
    x,y:longint;
    top,middle,bottom:longint;
    len:longint;
    offset:dword; 
    
    invW:single;
    Z,Zstep:single;
    W,Wstep:single;
    U,Ustep,V,Vstep:single;
    tX,ty:longint;

begin



    top:=0;
    bottom:=0;

    for x:=0 to poly.numVertex-1 do begin
        if poly.v[top].v.y > poly.v[x].v.y then top:=x;
        if poly.v[bottom].v.y < poly.v[x].v.y then bottom:=x;
    end;

    x:=top;
    y:=top;

    dec(y);
    if y<0 then y:=poly.numVertex-1;

    repeat

        SetSide(poly.v[x],poly.v[y],vp.rightside);


        x:=y;

        dec(y);
        if y<0 then y:=poly.numVertex-1;

    until x=bottom;


    x:=top;
    y:=top;

    inc(y);
    if y>= poly.numVertex then y:=0;

    repeat


        SetSide(poly.v[x],poly.v[y],vp.leftside);

        x:=y;

        inc(y);
        if y>= poly.numVertex then y:=0;


    until x=bottom;

{
    middle:=ceil((poly.v[top].v.y + poly.v[bottom].v.y) / 2);

    if vp.leftside[middle].offset > vp.rightside[middle].offset then begin
        vp.tempSide:=vp.leftside;
        vp.leftside:=vp.rightside;
        vp.rightside:=vp.tempSide;
    end;
}

    for y:=ceil(poly.v[top].v.y) to ceil(poly.v[bottom].v.y)-1 do begin
        

        len:=vp.rightSide[y].offset - vp.leftSide[y].offset;
        if len <= 0 then continue;

        Zstep:=(vp.rightSide[y].z-vp.leftSide[y].z) / len;
        Ustep:=(vp.rightSide[y].u-vp.leftSide[y].u) / len; 
        Vstep:=(vp.rightSide[y].v-vp.leftSide[y].v) / len; 
        Wstep:=(vp.rightSide[y].w-vp.leftSide[y].w) / len; 

        offset:=vp.leftSide[y].offset;

        z:=vp.leftSide[y].z + Zstep*vp.leftSide[y].subpix;
        u:=vp.leftSide[y].u + Ustep*vp.leftSide[y].subpix; 
        v:=vp.leftSide[y].v + Vstep*vp.leftSide[y].subpix; 
        w:=vp.leftSide[y].w + Wstep*vp.leftSide[y].subpix; 




        repeat 

            if (z+vp.clearReduction) > (vp.Zbuffer[offset]+vp.clearReduction) then begin 
                invW:=1 / w;


                        tx:=round((u*invW)*(texture.width-1));  
                        ty:=round((v*invW)*(texture.height-1));
                        


                    pdword(pointer2nativeUint(vp.screen.data) + offset shl 2)^:=getPixelclip(texture,tx,ty);


                    vp.Zbuffer[offset]:=z; 


            end; 

            inc(offset);
            z:=z + Zstep;
            w:=w + Wstep; 
            u:=u + Ustep; 
            v:=v + Vstep; 

            dec(len); 
        until len=0; 


    end;


end;



bringe bitte ein Codebeispiel

Werbeanzeige