Z -buffering - Z-buffering
En dybdebuffer , også kendt som en z-buffer , er en type databuffer, der bruges i computergrafik til at repræsentere dybdeoplysninger om objekter i 3D-rum fra et bestemt perspektiv . Dybdebuffere er et hjælpemiddel til at gengive en scene for at sikre, at de korrekte polygoner korrekt blokerer andre polygoner. Z-buffering blev først beskrevet i 1974 af Wolfgang Straßer i sin ph.d.-afhandling om hurtige algoritmer til gengivelse af okkluderede objekter. En lignende løsning til bestemmelse af overlappende polygoner er malerens algoritme , som er i stand til at håndtere ikke-uigennemsigtige sceneelementer, dog på bekostning af effektivitet og forkerte resultater.
I en 3D-rendering pipeline , når et objekt projiceres på skærmen, sammenlignes dybden (z-værdi) af et genereret fragment i det projicerede skærmbillede med den værdi, der allerede er gemt i bufferen ( dybde test ), og erstatter det hvis den nye værdi er tættere på. Det fungerer sammen med rasterizer , der beregner de farvede værdier. Fragmentet udsendt af rasterizer gemmes, hvis det ikke overlappes af et andet fragment.
Når man ser et billede, der indeholder delvis eller fuldstændigt overlappende uigennemsigtige objekter eller overflader, er det ikke muligt fuldt ud at se de objekter, der er længst væk fra betragteren og bag andre objekter (dvs. nogle overflader er skjult bag andre). Hvis der ikke var nogen mekanisme til håndtering af overlappende overflader, ville overflader gengive oven på hinanden, uden at være ligeglade med, om de er beregnet til at ligge bag andre genstande. Identifikation og fjernelse af disse overflader kaldes problemet med skjult overflade . For at kontrollere overlapning beregner computeren z-værdien af en pixel, der svarer til det første objekt, og sammenligner den med z-værdien på den samme pixelplacering i z-bufferen. Hvis den beregnede z-værdi er mindre end z-værdien allerede i z-bufferen (dvs. den nye pixel er tættere), erstattes den aktuelle z-værdi i z-bufferen med den beregnede værdi. Dette gentages for alle objekter og overflader i scenen (ofte parallelt ). I sidste ende tillader z-bufferen korrekt gengivelse af den sædvanlige dybdeopfattelse: et tæt objekt skjuler en længere væk. Dette kaldes z-culling .
Z-bufferen har den samme interne datastruktur som et billede, nemlig et 2d-array, med den eneste forskel, at den gemmer en enkelt værdi for hver skærmpixel i stedet for farvebilleder, der bruger 3 værdier til at skabe farve. Dette får z-bufferen til at se sort-hvid ud, fordi den ikke gemmer farveoplysninger. Bufferen har de samme dimensioner som skærmbufferen for konsistens.
Primære synlighedstest (f.eks. Tilbageslag ) og sekundære synlighedstests (f.eks. Overlapningstjek og skærmklipning) udføres normalt på objekters polygoner for at springe over bestemte polygoner, der er unødvendige at gengive. Z-buffer er til sammenligning forholdsvis dyr , så udførelse af primære og sekundære synlighedstests aflaster z-bufferen for en vis pligt.
Granulariteten af en z-buffer har stor indflydelse på scenekvaliteten: den traditionelle 16-bit z-buffer kan resultere i artefakter (kaldet " z-fight " eller syning ), når to objekter er meget tæt på hinanden. En mere moderne 24-bit eller 32-bit z-buffer opfører sig meget bedre, selvom problemet ikke kan elimineres uden yderligere algoritmer. En 8-bit z-buffer bruges næsten aldrig, da den har for lidt præcision.
Anvendelser
Z-bufferen er en teknologi, der bruges i næsten alle nutidige computere, bærbare computere og mobiltelefoner til udførelse af 3D-computergrafik . Den primære brug nu er til videospil , som kræver hurtig og præcis behandling af 3d -scener. Z-bufferen er implementeret i hardware inden for forbruger- grafikkort . Z-bufferen bruges også (implementeret som software i modsætning til hardware) til fremstilling af computergenererede specialeffekter til film.
Desuden tillader Z-bufferdata opnået ved gengivelse af en overflade fra et lys synspunkt at skabe skygger ved hjælp af skyggekortlægningsteknikken .
Udviklinger
Selv med lille nok granularitet kan der opstå kvalitetsproblemer, når præcisionen i z-buffers afstandsværdier ikke spredes jævnt over afstanden. Nærmere værdier er meget mere præcise (og kan derfor vise tættere objekter bedre) end værdier, der er længere væk. Generelt er dette ønskeligt, men nogle gange vil det få artefakter til at dukke op, når objekter bliver mere fjerne. En variation af z-buffering, der resulterer i mere jævnt fordelt præcision, kaldes w-buffering (se nedenfor ).
Ved starten af en ny scene skal z-bufferen ryddes til en defineret værdi, normalt 1,0, fordi denne værdi er den øvre grænse (på en skala fra 0 til 1) for dybde, hvilket betyder, at der ikke er noget objekt til stede ved dette punkt gennem betragtningsfrustum .
Opfindelsen af z-buffer-konceptet tilskrives oftest Edwin Catmull , selvom Wolfgang Straßer beskrev denne idé i sin ph.d. fra 1974. speciale måneder før Catmulls opfindelse.
På nyere PC grafikkort (1999-2005), i z-buffer ledelse anvender en væsentlig bid af den tilgængelige hukommelse båndbredde . Der er blevet anvendt forskellige metoder til at reducere ydelsesomkostningerne ved z-buffering, såsom tabsfri komprimering (computerressourcer til komprimering/dekomprimering er billigere end båndbredde) og ultrahurtig hardware z-clear, der gør forældet "en ramme positiv, en ramme negativt "trick (springer helt mellem rammen helt over ved hjælp af signerede numre til smart at kontrollere dybder).
Z-slagtning
I gengivelse er z-culling tidlig pixeleliminering baseret på dybde, en metode, der giver en stigning i ydeevnen, når gengivelse af skjulte overflader er dyrt. Det er en direkte konsekvens af z-buffering, hvor dybden af hver pixelkandidat sammenlignes med dybden af den eksisterende geometri, bag hvilken den kan være skjult.
Når du bruger en z-buffer, kan en pixel slettes (kasseres), så snart dens dybde er kendt, hvilket gør det muligt at springe hele processen med belysning og teksturering over en pixel, der alligevel ikke ville være synlig . Også tidskrævende pixel-shaders vil generelt ikke blive udført for de fjernede pixels. Dette gør z-culling til en god optimeringskandidat i situationer, hvor fillrate , belysning, teksturering eller pixel shaders er de vigtigste flaskehalse .
Mens z-buffering tillader geometrien at være usorteret, kan sortering af polygoner ved at øge dybden (dermed ved hjælp af en omvendt malers algoritme ) gengive hver skærmpixel færre gange. Dette kan øge ydeevnen i scener med begrænset fyldning med store mængder overtræk, men hvis den ikke kombineres med z-buffering, lider den af alvorlige problemer som:
- polygoner kan lukke hinanden i en cyklus (f.eks. trekant A lukker B, B lukker C, C lukker A), og
- der er ikke noget kanonisk "tættest" punkt på en trekant (f.eks .: uanset om man sorterer trekanter efter deres midterpunkt eller nærmeste punkt eller længste punkt, kan man altid finde to trekanter A og B sådan, at A er "tættere", men i virkeligheden B skal først tegnes).
Som sådan kan en omvendt malers algoritme ikke bruges som et alternativ til Z-culling (uden anstrengende ombygning), undtagen som en optimering til Z-culling. For eksempel kan en optimering være at holde polygoner sorteret efter x/y-placering og z-dybde for at give grænser, i et forsøg på hurtigt at afgøre, om to polygoner muligvis kan have en okklusionsinteraktion.
Matematik
Intervallet for dybdeværdier i kamerarum, der skal gengives, defineres ofte mellem a og værdien af .
Efter en perspektivtransformation defineres den nye værdi af eller :
Efter en ortografisk fremskrivning defineres den nye værdi af , eller , af:
hvor er den gamle værdi af i kamerarum, og kaldes undertiden eller .
De resulterende værdier af normaliseres mellem værdierne af -1 og 1, hvor flyet er på -1 og flyet er på 1. Værdier uden for dette område svarer til punkter, som ikke i visningsområdet keglestub , og burde ikke være gengivet.
Fixed-point repræsentation
Typisk lagres disse værdier i z-buffer af hardware grafikacceleratoren i fast punkt format. Først normaliseres de til et mere almindeligt område, som er [0, 1] ved at erstatte den passende konvertering til den tidligere formel:
Forenkling:
For det andet ganges ovenstående formel med hvor d er dybden af z-bufferen (normalt 16, 24 eller 32 bit) og afrunding af resultatet til et helt tal:
Denne formel kan inverteres og afledes for at beregne z-bufferopløsningen ('granulariteten' nævnt tidligere). Det omvendte af ovenstående :
hvor
Z-bufferopløsningen med hensyn til kameraplads ville være den inkrementelle værdi, der skyldes den mindste ændring i heltalet, der er gemt i z-bufferen, som er +1 eller -1. Derfor kan denne opløsning beregnes ud fra derivatet som en funktion af :
Udtrykker det tilbage i kamerarum ved at erstatte med ovenstående :
Dette viser, at værdierne for er grupperet meget tættere nær flyet og meget mere tyndt længere væk, hvilket resulterer i bedre præcision tættere på kameraet. Jo mindre den er, jo mindre præcision er der langt væk - at have flyet sat for tæt er en almindelig årsag til uønskede gengivelse af artefakter i fjernere objekter.
At gennemføre en z-buffer, værdierne af er lineært interpoleret over skærmen rummet mellem toppunkterne i den nuværende polygon er, og disse mellemliggende værdier lagres normalt i z-buffer i fast punkt format.
W-buffer
For at implementere en w-buffer lagres de gamle værdier i kamerarummet eller i bufferen, generelt i flydende punktformat . Disse værdier kan imidlertid ikke lineært interpoleres på tværs af skærmrummet fra hjørnerne - de skal normalt vendes , interpoleres og derefter inverteres igen. De resulterende værdier af , i modsætning til , er fordelt jævnt mellem og . Der er implementeringer af w-bufferen, der helt undgår inversionerne.
Om en z-buffer eller w-buffer resulterer i et bedre billede, afhænger af applikationen.
Algoritmik
Følgende pseudokode demonstrerer processen med z-buffering:
// First of all, initialize the depth of each pixel.
d(i, j) = infinite // Max length
// Initialize the color value for each pixel to the background color
c(i, j) = background color
// For each polygon, do the following steps :
for (each pixel in polygon's projection)
{
// Find depth i.e, z of polygon
// at (x, y) corresponding to pixel (i, j)
if (z < d(i, j))
{
d(i, j) = z;
c(i, j) = color;
}
}