Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Normal + Environment mapping

[es] :: 3D programiranje :: Normal + Environment mapping

[ Pregleda: 2614 | Odgovora: 3 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

glorius
Damir Nikolic
C++ developer
SR

Član broj: 4366
Poruke: 428
77.46.233.*

ICQ: 208550327


+14 Profil

icon Normal + Environment mapping31.03.2010. u 18:10 - pre 171 meseci
Zelim da kombinujem Bump + Reflection efekat u shaderu....

Code:


void LightingVSNormal(    float3 posL : POSITION0,
                        float3 tangentL : TANGENT0,
                        float3 binormalL : BINORMAL0, 
                         float3 normalL : NORMAL0,
                          float2 texCoord : TEXCOORD0, 
                        out float4 oPosH : POSITION0, 
                        out float3 oEyeVec : TEXCOORD0,
                        out    float3 oLightVec : TEXCOORD1, 
                        out float2 oTexCoord : TEXCOORD2, 
                        out float3x3 oTBN : TEXCOORD3, 
                        out float3   oToCamObjectSpace : TEXCOORD6)
{
    float3x3 TBN;
    TBN[0] = tangentL;
    TBN[1] = binormalL;
    TBN[2] = normalL;
    
    oTBN = TBN;
    
    float3         camPosL = mul( float4(g_camPos, 1.0f), g_matWorldInv );
    oToCamObjectSpace = (camPosL - posL); 
    oEyeVec = mul( TBN, oToCamObjectSpace );
    
    float3         lightDir = mul( float4(g_lightDir, 0.0f), g_matWorldInv );
    oLightVec = mul(TBN, lightDir);
    
    
    oPosH = mul( float4( posL, 1.0f ), g_matWVP );  
    oTexCoord = texCoord;
}

float4 LightingPSNormal( float3 camVec : TEXCOORD0,
                         float3 lightVec : TEXCOORD1, 
                         float2 texCoord : TEXCOORD2, 
                         float3x3 TBN : TEXCOORD3, 
                         float3   toCamObjectSpace : TEXCOORD6) : COLOR0
{
    camVec = normalize(camVec);
    lightVec = normalize(lightVec);
    
    float3 normalT = tex2D(g_samNormal, texCoord);
    
    normalT = 2.0f*normalT - 1.0f;
    normalT = normalize(normalT);
    
    float      spec = calculateSpecularFactor( lightVec, normalT, camVec );
    float     diff = calculateDiffuseFactor( -lightVec, normalT );
    
    // reflection 

        // transformisemo  normalu u object space
    float3 normalObject = normalize(mul(normalT, TBN));
    
    float3 reflectedColor = 0;
    
        if(g_bReflecting)
        {
                // racunamo refleksiju u object space
        float3     envMapTex = reflect(-normalize(toCamObjectSpace), normalObject);
                reflectedColor = texCUBE(g_samEnv, envMapTex);
        }
    
    float4  diffuseColor = diff*tex2D(g_samDiffuse, texCoord);
    
    if(g_bReflecting)
    {
        diffuseColor = float4(g_fReflectivity*reflectedColor, 1.0f) + (1.0f - g_fReflectivity)*diffuseColor;
    }
    
    float4  specularColor = diff == 0.0f ? 0.0f : spec*float4(1, 1, 1, 1);
    float4  ambientColor = 0.1f*tex2D(g_samDiffuse, texCoord);
    float4  glowColor = tex2D(g_samGlow, texCoord);
    float4  finalColor = ambientColor + glowColor + diffuseColor + specularColor;
    
    if(g_bSelected == true)
        finalColor*=float4(1.0f, 0.1f, 0.1f, 1.0f) + float4(0.5f, 0, 0, 1);
    
    return  finalColor;
}

technique techLightingNormal
{
    pass p0
    {
        vertexshader = compile VS_PROFILE LightingVSNormal();
        pixelshader = compile PS_PROFILE LightingPSNormal();    
    }
}




Posmatracu sledeci deo koda koji je zaduzen za refleksiju:

Code:


float3 normalObject = normalize(mul(normalT, TBN));
    
    float3 reflectedColor = 0;
    
        if(g_bReflecting)
        {
                // racunamo refleksiju u object space
        float3     envMapTex = reflect(-normalize(toCamObjectSpace), normalObject);
                reflectedColor = texCUBE(g_samEnv, envMapTex);
        }



normalT se racuna u tangent (texture) space. Ona je priblizna pravcu Z ose ( ili je paralelena sa Z osom ako je flat surface ), tako da je uvek pozitivna tako da se envMapTex ne moze racunati u tangent space.

float3 normalObject = normalize(mul(normalT, TBN));

Mnozenjem sa TBN prevodim normalT u object space. Camera vektor je isto u object space tako da sada mogu da proracunam reflection vektor.

Problem je sto nigde nisam video da se ovo radi na ovaj nacin :) Meni se cini da je proracun korektan posto se normala rotira iz tangent space u object space tako da se dovodi u isti koordinatni sistem u kojem je i kamera.

[url= http://i44.tinypic.com/w0hnpg.jpg ]Evo [/url]kako sve to izgleda u mom Mesh Editoru.

Na netu sam nasao nacin rekalkulisanja Z komponente:

Primer koda:

half3 N=normalize( half3( Nxy * bumpCoeff,sqrt( 1 - Nxy.x * Nxy.x - Nxy.y * Nxy.y)) );

Mozda je to bolje resenje... Mene zanima kako to, u stvari, treba pravilno uraditi. :)




[Ovu poruku je menjao glorius dana 31.03.2010. u 21:46 GMT+1]
EOF
 
Odgovor na temu

Filip Strugar
Filip Strugar
UK

Član broj: 9871
Poruke: 383
*.zone7.bethere.co.uk.



+1 Profil

icon Re: Normal + Environment mapping04.04.2010. u 15:49 - pre 170 meseci
Deluje sve OK u principu osim sto kad semplujes environment mapu za refleksiju, to radis sa vektorom koji je u object space-u, a tekstura refleksije ce obicno (uvek) biti u world space-u.

Samo mnogo je jednostavnije (i manje matematike, i mnogo manje stvari treba da saljes iz VS u PS, sto koshta) da sve prevodis odmah u world space i tu radis proracune za svetlo - onda takodje neces imati ovaj problem sa refleksijama odozgo, itd.
Tako da pretvori onu 'out float3x3 oTBN' matricu iz 'tangent->object' u 'tangent->object->world' i onda mozes da izbacis par onih drugih stvari iz vertex shadera jer ti ne treba light u object space-u nego u world, itd.

Sto se bump/normal mape tice, najcesce se koristi normal mapa kao sto ti radis (koja je u tangent space-u, pa je onda pretvoris u object tj trebalo bi u world).

To je onda normal-mapping.

Ne znam tacno sta je onaj primer koji navodis, ono rekalkulisanje Z komponente ali lici na dekompresiju normale?

Napisacu ti objasnjenje/primer za to u sledecoj poruci, moram sad da begam neshto.
 
Odgovor na temu

Filip Strugar
Filip Strugar
UK

Član broj: 9871
Poruke: 383
*.zone7.bethere.co.uk.



+1 Profil

icon Re: Normal + Environment mapping04.04.2010. u 16:29 - pre 170 meseci
Daklem, onaj kod

Code:
half3 N=normalize( half3( Nxy * bumpCoeff,sqrt( 1 - Nxy.x * Nxy.x - Nxy.y * Nxy.y)) );


deluje kao dekompresija normale iz .xy komponente, a taj bumpCoeff izgleda da sluzi tome da povecava 'bumpiness' (jacinu normala) ali zasto to nije podeseno u samoj normal mapi nemam pojma.


Normal map tekstura zauzima dosta prostora i zgodno je ako se moze nekako kompresovati. Ako se samo propusti kroz DXT1 algoritam dobijaju se prilicno gadni artifakti, toliko ruzni da je skoro neupotrebljivo. Postoje raznorazni algoritmi za kompresiju normala, ali ako hoces nesto sto je svuda podrzano na DirectX9 onda je najbolja opcija koristiti DXT5, gde u .r zapises .x, u .a zapises .y a .z rekonstruises u pixel shader-u. To se cesto zove DXT5_NM i postoji par alatki koje snimaju/konvertuju u taj format ako te mrzi da to radis rucno (npr one NVidia texture/normalmap tools, mada se ne secam detalja.)

To ti daje prilicno dobru kompresiju normal mape, a dekompresija onda izgleda ovako:

Code:

float3 UncompressDXT5_NM(float4 normPacked)
{
   float3 norm = float3( normPacked.a * 2.0 - 1.0, normPacked.r * 2.0 - 1.0, 0 );
   norm.z = sqrt( 1 - norm.x * norm.x - norm.y * norm.y );
   return norm;
}


(razlog zasto .z mozes ovako lako da rekonstruises iz .xy je to sto uvek znas da je z pozitivan u slucaju normal mape - normala uvek pokazuje bar malo na gore u odnosu na povrsinu na kojoj se nalazi)



Naravno ovo je sve optimizacija i verovatno nepotrebno za pocetak!
 
Odgovor na temu

glorius
Damir Nikolic
C++ developer
SR

Član broj: 4366
Poruke: 428
*.dynamic.isp.telekom.rs.

ICQ: 208550327


+14 Profil

icon Re: Normal + Environment mapping05.04.2010. u 19:23 - pre 170 meseci
Evo prepravljenog shadera koji racuna sve u world space:

Code:


void LightingVSNormal(    float3 posL : POSITION0,
                        float3 tangentL : TANGENT0,
                        float3 binormalL : BINORMAL0, 
                         float3 normalL : NORMAL0,
                          float2 texCoord : TEXCOORD0, 
                        out float4 oPosH : POSITION0, 
                        out float3 oCamVec : TEXCOORD0,
                        out    float3 oLightVec : TEXCOORD1, 
                        out float2 oTexCoord : TEXCOORD2, 
                        out float3x3 oTBN : TEXCOORD3)
{
    float3x3 TBN;
        TBN[0] = tangentL;
        TBN[1] = binormalL;
        TBN[2] = normalL;
    
        oTBN = TBN;

        // ne znam da li treba ovako
        // TBN konvertuje iz tangent to object. Mnozenjem g_matWorldIT matricom konvertujemo u world koordinatni sistem
        oTBN = mul(oTBN, g_matWorldIT);
    
        float3        posW = mul( float4(posL, 1.0f), g_matWorld);

        oCamVec = normalize(g_camPos - posW); 
        oLightVec = normalize(g_lightDir);
    
        oPosH = mul( float4( posL, 1.0f ), g_matWVP );
        oTexCoord = texCoord;
}

float4 LightingPSNormal( float3 camVec : TEXCOORD0,
                         float3 lightVec : TEXCOORD1, 
                         float2 texCoord : TEXCOORD2, 
                         float3x3 TBN : TEXCOORD3) : COLOR0
{
    camVec = normalize(camVec);
    lightVec = normalize(lightVec);
    
    float3 normalT = tex2D(g_samNormal, texCoord);
    
    normalT = 2.0f*normalT - 1.0f;
    normalT = normalize(normalT);
    
    float3 normalWorld= normalize(mul(normalT, TBN));
    
    float      spec = calculateSpecularFactor( lightVec, normalWorld, camVec );
    float     diff = calculateDiffuseFactor( -lightVec, normalWorld );
    
    // reflection 
    
    float3 reflectedColor = 0;
    
        if(g_bReflecting)
        {
        float3     envMapTex = reflect(-camVec, normalWorld);
                reflectedColor = texCUBE(g_samEnv, envMapTex);
        }
    
    float4  diffuseColor = diff*tex2D(g_samDiffuse, texCoord);
    
    if(g_bReflecting)
    {
        diffuseColor = float4(g_fReflectivity*reflectedColor, 1.0f) + (1.0f - g_fReflectivity)*diffuseColor;
    }
    
    float4  specularColor = diff == 0.0f ? 0.0f : spec*float4(1, 1, 1, 1);
    float4  ambientColor = 0.1f*tex2D(g_samDiffuse, texCoord);
    float4  glowColor = tex2D(g_samGlow, texCoord);
    float4  finalColor = ambientColor + glowColor + diffuseColor + specularColor;
    
    if(g_bSelected == true)
        finalColor*=float4(1.0f, 0.1f, 0.1f, 1.0f) + float4(0.5f, 0, 0, 1);
    
    finalColor.a = g_fAlpha;
    
    return  finalColor;
}



Wow! Ovo deluje mnogo bolje i lakse je za razumevanje i odrzavanje.
Da je samo uradjen normal mapping onda bi sve ovo bilo bolje raditi u tangent space-u. Ali, posto do sada nisam radio ovakav shader, nisam znao koji space da izaberem i cini mi se da je ovo best solution.

Hvala na odgovoru :))

[Ovu poruku je menjao glorius dana 05.04.2010. u 21:05 GMT+1]

[Ovu poruku je menjao glorius dana 06.04.2010. u 01:36 GMT+1]
EOF
 
Odgovor na temu

[es] :: 3D programiranje :: Normal + Environment mapping

[ Pregleda: 2614 | Odgovora: 3 ] > FB > Twit

Postavi temu Odgovori

Srodne teme
Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.