Forum Sveta kompjutera

Nazad   Forum Sveta kompjutera > Test Run > Programiranje > Pravljenje igara
Uputstvo Članstvo Kalendar Današnje poruke Pretraži

Pravljenje igara Programski jezici, tehnike, alatke u službi pravljenja igara...

Odgovor
 
Alatke vezane za temu Vrste prikaza
Stara 24.11.2013, 17:01   #1
Lucic Nemanja
Starosedelac
 
Član od: 2.12.2005.
Lokacija: Beograd
Poruke: 1.241
Zahvalnice: 65
Zahvaljeno 76 puta na 49 poruka
Slanje poruke preko Skypea korisniku Lucic Nemanja
Određen forumom O svetlu u igrama

Naiđoh na konkretan problem, ali reko zašto u sto vreme i ne otvoriti temu koja se generalno bavi algoritmima za osvetljenje i shading. Izvinjavam se ako već postoji .

Elem, moj problem je sledeći. Radio sam ovih dana Light Pre-Pass i uspeo nakon dugog lupanja glavom o zid da ga implementiram, i nakon toga čitav sistem za osvetljenje scene da ispeglam sa snekama. I sve je išlo koliko toliko ok, dok nisam odlučio da implementiram i specular highlights. Koristio sam običnu Phong formulu i račun sam radio u pixel shaderu gde računam teksturu za sveto. Međutim dobijao sam čudne rezultate...

Spoiler za slika:




Ok, highlight je na mestu ali nešto očigledno nije uredu sa njim. Zašto je tako "iseckan"? Je l' neko možda upoznat sa ovim problemom?
Priložene slike
Kliknite na sliku za veću verziju

Ime:	WindowsGame-2013-11-24-15-50-32-07.jpg
Viđeno:	329 puta
Veličina:	66,5 KB
ID:	47728  
Lucic Nemanja je offline   Odgovor sa citatom ove poruke
Stara 24.11.2013, 17:15   #2
Belphegor
V.I.P. Programiranje
 
Član od: 29.8.2007.
Lokacija: Valjevo
Poruke: 1.349
Zahvalnice: 983
Zahvaljeno 371 puta na 280 poruka
Određen forumom Re: O svetlu u igrama

Koji ti je format za buffer normala?
Pokazi vertex/pixel shader za taj prolaz i pixel shader gde samplujes taj buffer za kalkulacije svetla.
Belphegor je offline   Odgovor sa citatom ove poruke
Stara 24.11.2013, 17:24   #3
Lucic Nemanja
Starosedelac
 
Član od: 2.12.2005.
Lokacija: Beograd
Poruke: 1.241
Zahvalnice: 65
Zahvaljeno 76 puta na 49 poruka
Slanje poruke preko Skypea korisniku Lucic Nemanja
Određen forumom Re: O svetlu u igrama

Citat:
Belphegor kaže: Pregled poruke
Koji ti je format za buffer normala?
Pokazi vertex/pixel shader za taj prolaz i pixel shader gde samplujes taj buffer za kalkulacije svetla.
32-bit ARGB, 8 bita po kanalu.

Spoiler za DepthNormal shader:

Kod:
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4x4 viewProjection = mul(View, Projection);
    float4x4 worldViewProjection = mul(World, viewProjection);
	    
    output.Position = mul(input.Position, worldViewProjection);
    output.Normal = mul(input.Normal, World);
    output.Depth.xy = output.Position.zw;

    return output;
}


PixelShaderOutput PixelShaderFunction(VertexShaderOutput input)
{
	PixelShaderOutput output;
	
	output.Depth = input.Depth.x / input.Depth.y;
	output.Normal.xyz = (normalize(input.Normal).xyz / 2) + .5;
	
	output.Depth.a = 1;
	output.Normal.a = 1;
	
    return output;
}
}


Spoiler za Light Pixel Shader:

Kod:
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
	float3 color = 1;
	// Find the pixel coordinates of the input position in the depth
	// and normal textures
	float2 texCoord = postProjToScreen(input.LightPosition) + halfPixel();
	
	// Extract the depth for this pixel from the depth map
	float4 depth = tex2D(depthSampler, texCoord);
	
	// Recreate the position with the UV coordinates and depth value
	float4 position;
	position.x = texCoord.x * 2 - 1;
	position.y = (1 - texCoord.y) * 2 - 1;
	position.z = depth.r;
	position.w = 1.0f;

	// Transform position from screen space to world space
	position = mul(position, InvViewProjection);
	position.xyz /= position.w;
	
	float3 viewDirection = position - CameraPosition;

	// Extract the normal from the normal map and move from
	// 0 to 1 range to -1 to 1 range
	float4 normal = (tex2D(normalSampler, texCoord) - .5) * 2;
		
	// Perform the lighting calculations for a point light
	if (IsPointLight)
	{
		float3 pointLightDirection = normalize(PointLightPosition - position);
		float pointLighting = 1;
		pointLighting = clamp(dot(normal, pointLightDirection), 0, 1);
		
		float d = distance(PointLightPosition, position);
		float att = clamp(1 - pow(d / PointLightAttenuation, 6), 0, 1);

		float3 pointLightAmount = pointLighting * att * LightPower;

		// Add specular highlights
		float3 refl = reflect(pointLightDirection, normal);
		float3 view = normalize(viewDirection);

		pointLightAmount += pow (saturate(dot(refl, view)), SpecularPower) * SpecularColor;

		color *= pointLightAmount;
	}

	//Preform the lighting calculation for a directional light
	if (IsDirectionalLight)
	{
		normalize(DirectionalLightDirection);
		float directionalLightAmount = clamp(dot(normal, -DirectionalLightDirection), 0, 1) * LightPower;

		// Add specular highlights
		float3 refl = reflect(DirectionalLightDirection, normal);
		float3 view = normalize(viewDirection);

		directionalLightAmount += pow (saturate(dot(refl, view)), SpecularPower) * SpecularColor;

		color *= directionalLightAmount;
	}

	
    return float4(LightColor * color, 1);
}


Spoiler za Pixel shader gde samplujem Light Texture:

Kod:
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
	// Sample model's texture
	float3 basicTexture = tex2D(basicTextureSampler, input.UV);
	
	if (!TextureEnabled)
		basicTexture = float4(1, 1, 1, 1);
		
	// Extract lighting value from light map
	float2 texCoord = postProjToScreen(input.PositionCopy) + halfPixel();
	float3 light = tex2D(lightSampler, texCoord);
	
	light += AmbientColor;

	// Calculating Projective Texturing
	float3 projection = float3(0, 0, 0);
	if (ProjectorEnabled)
		projection = sampleProjector(postProjToScreen(input.ProjectorScreenPosition) + halfPixel());

	// Calculating Shadows
	float shadow = 1;
	if (DoShadowMapping)
	{
		float2 shadowTexCoord = postProjToScreen(input.ShadowScreenPosition) + halfPixel();
		//float mapDepth = sampleShadowMap(shadowTexCoord).r;

		float realDepth = input.ShadowScreenPosition.z / ShadowFarPlane - ShadowBias;

		if (realDepth < 1)
		{
			float2 moments = sampleShadowMap(shadowTexCoord);
			float lit_factor = (realDepth <= moments.x);
			float E_x2 = moments.y;
			float Ex_2 = moments.x * moments.x;
			float variance = min(max(E_x2 - Ex_2, 0.0) + 1.0f / 10000.0f, 1.0);
			float m_d = (moments.x - realDepth);
			float p = variance / (variance + m_d * m_d);

			shadow = clamp(max(lit_factor, p), ShadowMult, 1.0f);
		}
	}

	return float4(basicTexture * DiffuseColor * light * shadow + projection, 1);
}


Da napomenem za specular nisam ništa posebno kreirao, samo sam ga ubacio u light shader i dodaje se isti na čitavu scenu.
Lucic Nemanja je offline   Odgovor sa citatom ove poruke
Stara 24.11.2013, 17:36   #4
Belphegor
V.I.P. Programiranje
 
Član od: 29.8.2007.
Lokacija: Valjevo
Poruke: 1.349
Zahvalnice: 983
Zahvaljeno 371 puta na 280 poruka
Određen forumom Re: O svetlu u igrama

1.
Citat:
32-bit ARGB, 8 bita po kanalu.
8 bita po kanalu je malo za normale pa moze biti razlog za artefakte koje vidis, probaj sa floating point texturom kao npr. ARGB32F (mada je dovoljno i ARGB16F, kao u STALKER-u).

2.
Kod:
output.Normal = mul(input.Normal, World);
Normal je directional vektor, prema tome moras da ukines translation part tako sto postavljas w komponentu na 0
Kod:
output.Normal = mul(float4(input.Normal, 0.0f), World);
ili transformacijom sa 3x3 matrixom:
Kod:
output.Normal.xyz = mul(input.Normal.xyz, float3x3(World));

To je sto za sad vidim da mi smrdi.
Belphegor je offline   Odgovor sa citatom ove poruke
Sledeći korisnik se zahvaljuje korisniku Belphegor na korisnoj poruci:
Lucic Nemanja (24.11.2013)
Stara 24.11.2013, 18:23   #5
Lucic Nemanja
Starosedelac
 
Član od: 2.12.2005.
Lokacija: Beograd
Poruke: 1.241
Zahvalnice: 65
Zahvaljeno 76 puta na 49 poruka
Slanje poruke preko Skypea korisniku Lucic Nemanja
Određen forumom Re: O svetlu u igrama

Povećanje kanala je rešilo problem . Stavio sam 16x4 po kanalu. Hvala!
A čisto da napomenem da sam imao i bug sa senkama i usput odlučim da pogledam i format za shadow depth buffer kad ono i on RGBA po 8 bita, a koristim efektivno samo dva kanala, red i green!!! Em što sam imao problem sa kvalitetom senki jer sam smeštao u samo 8 bita, em što mi je 16 bita otišlo ni na šta . Promenio sam ga na 32 bita, 2x16 i senke rade perfektno !
Sve sam radio po nekoj knjizi koja je budi bog s nama...
Lucic Nemanja je offline   Odgovor sa citatom ove poruke
Stara 24.11.2013, 18:29   #6
Belphegor
V.I.P. Programiranje
 
Član od: 29.8.2007.
Lokacija: Valjevo
Poruke: 1.349
Zahvalnice: 983
Zahvaljeno 371 puta na 280 poruka
Određen forumom Re: O svetlu u igrama

Mozes da pakujes normale i u 32 bita ali onda povecavas broj instrukcija i kvalitet je upitan. Imas ovde zanimljiv artikal o raznim semama i pakovanja/raspakivanja za normale.
Belphegor je offline   Odgovor sa citatom ove poruke
Sledeći korisnik se zahvaljuje korisniku Belphegor na korisnoj poruci:
Lucic Nemanja (24.11.2013)
Stara 24.11.2013, 19:14   #7
Lucic Nemanja
Starosedelac
 
Član od: 2.12.2005.
Lokacija: Beograd
Poruke: 1.241
Zahvalnice: 65
Zahvaljeno 76 puta na 49 poruka
Slanje poruke preko Skypea korisniku Lucic Nemanja
Određen forumom Re: O svetlu u igrama

Proučiću ovih dana. Nego, imam još jedno pitanje, u vezi senki. Iz nekog razloga mi ne crta senke kada mnogo udaljim virtuelnu kameru koja predstavlja svetlo koje ih baca. Podesio sam far clip da bude dovoljno velik, i pogledao sam i iz same kamere da li pokriva sve što treba. Sve je ok. Međutim kada je mnogo odaljim neće da crta senke. Sačuvao sam buffere za shadowDepth i depth i dobio sam ovo:

Spoiler za Depth:




Spoiler za Shadow Depth:




Kapiram da je problem u depth baferu. Stavio sam format depth bafera 2x32. Morao sam to da stavim pošto koristim multilply render targets za depth i normal bafere, a normale su 4x16, pa mi je prijavljivao grešku da moraju biti iste veličine.

Shader je isti kao onaj gore, a evo koji mu je format output-a:

Kod:
struct PixelShaderOutput
{
	float4 Normal : COLOR0;
	float4 Depth : COLOR1;
};
Hvala unapred!
Priložene slike
Kliknite na sliku za veću verziju

Ime:	depth.png
Viđeno:	168 puta
Veličina:	2,6 KB
ID:	47730   Kliknite na sliku za veću verziju

Ime:	shadowDepth1600.jpg
Viđeno:	174 puta
Veličina:	55,8 KB
ID:	47731  
Lucic Nemanja je offline   Odgovor sa citatom ove poruke
Stara 24.11.2013, 20:16   #8
Belphegor
V.I.P. Programiranje
 
Član od: 29.8.2007.
Lokacija: Valjevo
Poruke: 1.349
Zahvalnice: 983
Zahvaljeno 371 puta na 280 poruka
Određen forumom Re: O svetlu u igrama

Postoji vise implementacija za shadow mape, ja cu probati da napisem o nacinu koji je "standardan" i koji uglavnom koriste svi jer radi na svakom hw-u.
Za shadow mape ti treba poseban RT (render target, odnosno shadow buffer) i DS (depth stencil surface)*.
Format za shadow buffer najidealnije treba da bude floating point textura, R32F (samo red kanal).
Kod:
r = z/w
Postavke near i far clip plan-ova postavljas "razumno", odnosno near da bude sto dalje od kamere moguce a far sto blize (a da ne klipujes objekte koje crtas), inace ces imati losiji kvalitet senki.

* Ne znam koji jezik koristis, sa C++-som kad kreiras uredjaj imas opciju dali da automatski kreira i DS povrsinu. Kad menjas RT (SetRenderTarget funkcija), RT koji postavis mora imati iste ili manje od DS dimenzije koja je trenutno postavljena (SetDepthStencilSurface funkcija).
Recimo ako imas 1024x768 frejm (client prostor na koji se crta) a shadow mape se obicno postavljaju da budu POT (power of two, 512x512-1024x1024-2048x2048...) pa moze da se desi da hoces recimo shadow buffer dimenzija 2048x2048, zato ti treba posebna DS povrsina (tako zahteva DX api).
Znaci imas nesto ovako:
Kod:
void DrawFrame() {
// DS je vec postavljen, ako si izabrao automatsko kreiranje i njegova velicina je kao i backbuffer (1024x768)
...
LPDIRECT3DSURFACE backBuffer;
device->GetRenderTarget(0, backBuffer); // "bekapujemo" backBUffer povrsinu jer nam treba kasnije da se postavi

// iz pogleda igraca
device->SetRenderTarget(0, DepthSurface);
device->SetRenderTarget(1, NormalSurface);
device->Clear( ..., TARGET | ZBUFFER | STENCIL...);

DrawScene(playerView, playerProjection);
...

// iz pogleda svetla
LPDIRECT3DSURFACE oldDS;
device->GetDepthStencilSurface(&oldDS);// "bekapujemo" DS povrsinu jer u sledecem koraku postavljamo novu za shadow buffer

device->SetDepthStencilSurface(shadowDS); // bez ovoga ces imati gresku ako je dimenzija shadow buffera veca od DS povrsine
device->SetRenderTarget(0, shadowSurface);// shadow buffer
device->SetRenderTarget(1, nullptr);// "deaktiviramo" MRT (multiple render targets) posto treba da crtamo samo na jedan RT
device->Clear( ..., TARGET | ZBUFFER | STENCIL...);

DrawScene(lightView, lightProjection);// crtamo na shadow buffer
...

// ovde smo zavrsili sa shadow bufferom i vracamo "stare" povrsine
oldDS->Release(); // Get... pozivi inkrementuju ref count pa se ovde poziva Release da ne bi doslo do curenja memorije
backBuffer->Release();// -||-
device->SetDepthStencilSurface(oldDS);
device->SetRenderTarget(0, backBuffer);

DrawSceneWithShadowMap();
...
}
Belphegor je offline   Odgovor sa citatom ove poruke
Sledeći korisnik se zahvaljuje korisniku Belphegor na korisnoj poruci:
Lucic Nemanja (24.11.2013)
Stara 25.11.2013, 14:03   #9
Lucic Nemanja
Starosedelac
 
Član od: 2.12.2005.
Lokacija: Beograd
Poruke: 1.241
Zahvalnice: 65
Zahvaljeno 76 puta na 49 poruka
Slanje poruke preko Skypea korisniku Lucic Nemanja
Određen forumom Re: O svetlu u igrama

Hvala. Uspeo sam da sredim sve sa senkama, uglavnom mi je razumno postavljane far i near ravni rešilo sve probleme. Do sad sam near ravan postavljao odmah ispred kamere, a far daleko, pa se onda u količniku gubila informacija jer je broj težio nuli. Još mi samo jedan problem postoji koji nikako ne mogu da provalim zašto.

Spoiler za slika:




Senke su mi malo ofsetovane. Sve mi se čini dobro, ne mogu ni da namirišem grešku...
Priložene slike
Kliknite na sliku za veću verziju

Ime:	WindowsGame-2013-11-25-13-01-00-57.jpg
Viđeno:	159 puta
Veličina:	93,7 KB
ID:	47733  
Lucic Nemanja je offline   Odgovor sa citatom ove poruke
Stara 25.11.2013, 14:49   #10
Belphegor
V.I.P. Programiranje
 
Član od: 29.8.2007.
Lokacija: Valjevo
Poruke: 1.349
Zahvalnice: 983
Zahvaljeno 371 puta na 280 poruka
Određen forumom Re: O svetlu u igrama

Posto sam predhodni post napamet pisao zaboravio sam gore da navedem da treba da se izmenjaju podesavanja i za viewport kad se menjaju RT.

Ofset koji vidis je odavno poznat problem sa shadow mapama i zove se peter panning, osim ako nemas negde drugde gresku u kodu.
Eventualno mozes da "maskiras" problem na licima koja ne "gledaju" prema "suncu" jer ionako nisu osvetljena, mozda ovako:
Kod:
// l - light direction (normalized)
// n - face normal (normalized)
float NdotL        = saturate( dot( n, l ) ); 
...
atten *= NdotL;
s'tim da treba podesiti i ambijentalno osvetljenje da se podudara sa senkama. U glavnom ne postoji generalno resenje, na dosta mesta ces morati koristiti razne "hakove" da sredis neke stvari.
Na zalost, za vece scene/objekte ne moze se dobiti zadovoljavajuci kvalitet senki sa jednom texturom/shadow bufferom, za takve stvari ljudi koriste CSM (cascaded shadow maps) ili PSSM (parallel split shadow maps), ne pitaj me za razliku jer ne znam ni sam. Za CSM imas primer kod u DirectX sdk samples folderima, doduse primer je za dx11 ali moze da se iskoristi i za dx9 jer je sva matematika nevezana za konkretan api (ovo sam i ja koristio).
I imam jedan sample demo koji sam sacuvao sa jedne stranice/artikla koja nazalost vise ne postoji, ali moze da posluzi za studiranje. U ovom demou nije adresirano "plivanje ivica" (edge shimmering) senki kad se kamera rotira za razliku od CSM dx demoa u kome je to reseno.

https://drive.google.com/file/d/0B-h...it?usp=sharing

Nikad nisam koristio google drive pa ne znam da li ce ovo raditi. Javi mi da li moze da se skine, postavio sam fajl kao "public".
Belphegor je offline   Odgovor sa citatom ove poruke
Stara 25.11.2013, 15:39   #11
Andross
Kekule Mekule
 
Avatar korisnika Andross
 
Član od: 8.12.2005.
Lokacija: Beograd
Poruke: 4.134
Zahvalnice: 649
Zahvaljeno 1.354 puta na 693 poruka
Slanje poruke preko Skypea korisniku Andross
Određen forumom Re: O svetlu u igrama

Sto se tice PSSM-a evo poredjenja:

Spoiler za Bez PSSM:


Spoiler za Sa PSSM:


Uglavnom, za istu scenu, distancu i velicinu teksture senki se dobija kvalitetniji rezultat ali je ujedno i sporija tehnika naravno. Sto ti je veca distanca crtanja senki to ce one biti sve losije jer se renderuju na manjoj povrsini istog render targeta, tako da verujem da ti je distanca bila toliko velika da je shader jednostavno odbijao da spakuje senku na toliko malu povrsinu
Andross je offline   Odgovor sa citatom ove poruke
Odgovor

Bookmarks sajtovi


Vaš status
Ne možete postavljati teme
Ne možete odgovarati na poruke
Ne možete slati priloge uz poruke
Ne možete prepravljati svoje poruke

BB kod: uključeno
Smajliji: uključeno
[IMG] kod: uključeno
HTML kod: isključeno


Slične teme
tema temu započeo forum Odgovora Poslednja poruka
Memorija ili grafika u igrama? nightflier Osnovne komponente 20 6.8.2008 17:15
Problem sa mreznim igrama Kum22 Komunikacioni uređaji i umrežavanje 1 26.6.2008 1:59
Widescreen u igrama DeCoy Grafika 9 5.4.2008 20:35
Problem sa grafickom u igrama!? B@NE Kvarovi 5 18.10.2007 18:07
Slusalice sa mikrofonom u igrama na 2 kompa + gde da ih ukljucim? polarnimeda Zvuk na računaru 15 16.10.2007 19:50


Sva vremena su po Griniču +2 h. Sada je 18:09.


Powered by vBulletin® verzija 3.8.7
Copyright ©2000–2024, vBulletin Solutions, Inc.
Hosted by Beograd.com