2012-07-01 16 views
6

Sto utilizzando Ogre3D come motore grafico.Sto facendo qualcosa di sbagliato con questo programma CG?

Creo una maglia manualmente che funziona bene, UV sono corretti e sono impostati per rappresentare le coordinate reticolo (per questo esempio la griglia è 10 x 10)

faccio nulla nel programma vertice e avere un semplice programma di frammentazione. Ho incluso entrambi i programmi oltre al file materiale da spiegare.

Il mio problema è che, anche con il filtro impostato su nessuno, i colori non sembrano venire fuori come la mia immagine originale (questa è solo un'immagine di prova che sto usando perché avevo problemi con la creazione manuale della texture in orco). Risulta che il problema non è il mio codice in orco ma più probabilmente qualcosa a che fare sia con il file materiale che con i programmi frammento/vertice.

Ho anche incluso uno screenshot dell'output a sinistra e l'immagine originale a destra. Lo shader di frammenti disegna anche una semplice griglia sopra la parte superiore in modo da poter assicurare che le coordinate uv siano state passate correttamente. Quali sembrano essere.

enter image description here

Tutta la comprensione sarebbe molto apprezzato come sono davvero sicuro di cosa sto facendo di sbagliato.

Materiale di file:

// CG Vertex shader definition 
vertex_program PlainTexture_VS cg    
{ 
    // Look in this source file for shader code 
    source GameObjStandard.cg 
    // Use this function for the vertex shader    
    entry_point main_plain_texture_vp  
    // Compile the shader to vs_1_1 format  
    profiles arbvp1  

    // This block saves us from manually setting parameters in code 
    default_params      
    { 
     // Ogre will put the worldviewproj into our 'worldViewProj' parameter for us. 
     param_named_auto worldViewProj worldviewproj_matrix   
     // Note that 'worldViewProj' is a parameter in the cg code. 
    } 
} 

// CG Pixel shader definition 
fragment_program PlainTexture_PS cg    
{ 
    // Look in this source file for shader code 
    source GameObjStandard.cg   
    // Use this function for the pixel shader  
    entry_point main_plain_texture_fp  
    // Compile to ps_1_1 format  
    profiles arbfp1    
} 

material PlainTexture 
{ 
    // Material has one technique 
    technique     
    { 
     // This technique has one pass 
     pass     
     { 
      // Make this pass use the vertex shader defined above 
      vertex_program_ref PlainTexture_VS  
      { 
      } 
      // Make this pass use the pixel shader defined above 
      fragment_program_ref PlainTexture_PS  
      { 
      } 
      texture_unit 0 
      { 
       filtering none 
       // This pass will use this 2D texture as its input 
       texture test.png 2d   
      } 
      texture_unit 1 
      { 
       texture textureatlas.png 2d 
       tex_address_mode clamp 
       filtering none 
      } 
     } 
    } 
} 

CG File:

void main_plain_texture_vp(
    // Vertex Inputs 
    float4 position  : POSITION, // Vertex position in model space 
    float2 texCoord0 : TEXCOORD0, // Texture UV set 0 

    // Outputs 
    out float4 oPosition : POSITION, // Transformed vertex position 
    out float2 uv0  : TEXCOORD0, // UV0 

    // Model Level Inputs 
    uniform float4x4 worldViewProj) 
{ 
    // Calculate output position 
    oPosition = mul(worldViewProj, position); 

    // Simply copy the input vertex UV to the output 
    uv0 = texCoord0; 
} 

void main_plain_texture_fp(
    // Pixel Inputs 
    float2 uv0  : TEXCOORD0, // UV interpolated for current pixel 

    // Outputs 
    out float4 color : COLOR, // Output color we want to write 

    // Model Level Inputs 
    uniform sampler2D Tex0: TEXUNIT0, 

uniform sampler2D Tex1: TEXUNIT1)  // Texture we're going to use 
{ 

//get the index position by truncating the uv coordinates 
float2 flooredIndexes = floor(uv0); 

if((uv0.x > 0.9 && uv0.x < 1.1) 
|| (uv0.x > 1.9 && uv0.x < 2.1) 
|| (uv0.x > 2.9 && uv0.x < 3.1) 
|| (uv0.x > 3.9 && uv0.x < 4.1) 
|| (uv0.x > 4.9 && uv0.x < 5.1) 
|| (uv0.x > 5.9 && uv0.x < 6.1) 
|| (uv0.x > 6.9 && uv0.x < 7.1) 
|| (uv0.x > 7.9 && uv0.x < 8.1) 
|| (uv0.x > 8.9 && uv0.x < 9.1)) { 
    float4 color1 = {1.0,0,0,0}; 
    color = color1; 
} else if((uv0.y > 0.9 && uv0.y < 1.1) 
|| (uv0.y > 1.9 && uv0.y < 2.1) 
|| (uv0.y > 2.9 && uv0.y < 3.1) 
|| (uv0.y > 3.9 && uv0.y < 4.1) 
|| (uv0.y > 4.9 && uv0.y < 5.1) 
|| (uv0.y > 5.9 && uv0.y < 6.1) 
|| (uv0.y > 6.9 && uv0.y < 7.1) 
|| (uv0.y > 7.9 && uv0.y < 8.1) 
|| (uv0.y > 8.9 && uv0.y < 9.1)) { 
    float4 color1 = {1.0,0,0,0}; 
    color = color1; 
} else { 
    //get the colour of the index texture Tex0 at this floored coordinate 
    float4 indexColour = tex2D(Tex0, (1.0/10)*flooredIndexes); 
    color = indexColour; 
} 
} 
+0

Grazie per l'editing, non ero sicuro di come mettere le immagini in :) –

+0

cambiare 'float4 indexColour = tex2D (Tex0, (1.0/10) * flooredIndexes);' a ' float4 indexColour = tex2D (Tex0, (1.0/20) * flooredIndexes); 'potrebbe risolvere il problema – hamed

+0

Non sono sicuro che ciò abbia aiutato o no, non ha risolto il problema. Il motivo per cui ho moltiplicato per 1/10 è perché gli indici di uv0 corrono attualmente da 0 a 10 sia nella direzione u che v. Applico questo valore perché è interpolato nel programma del frammento, quindi ottengo valori come 5.6, se applico questo valore ottengo 5 che diviso per il numero di tiles width (10) mi dà la coordinata uv di cui ho bisogno, 0.5 –

risposta

6

Ok, quindi il suo stato un po 'che ho trovato la soluzione ai miei problemi, purtroppo, non erano on-line in modo da sperare che questo aiuta chiunque con problemi simili .

Durante la creazione di qualsiasi texture si dovrebbe sempre fare le texture di una dimensione in texel 2^n * 2^m dove m e n sono la larghezza e l'altezza della texture. Questo è stato il mio primo errore, anche se non me ne sono reso conto al momento.

La ragione per cui non avevo individuato questo era perché il mio atlante di trama principale era basato su questo principio ed era una trama 1024 x 1024. Quello che non avevo preso in considerazione era la dimensione della texture che stavo creando come indice di texture. Dato che la mia mappa era 10 x 10 stavo creando una trama 10 x 10 per gli indici, questo presumo di essere allungato in qualche modo (non so come funziona nel back-end) per essere 16 x 16 o 8 x 8, mescolando il texel insieme come ha fatto.

La prima cosa che mi ha dato l'idea è stata quando ho ridimensionato la mia tela in Photoshop e ho scoperto che i colori miscelati che crea erano uguali a quelli che avevo sul mio output di ogre3d.

ogni modo di passare ..

Una volta avevo capito questo sono stato in grado di creare la trama in Ogre e farlo passare attraverso la seguente

//Create index material 
Ogre::TexturePtr indexTexture = Ogre::TextureManager::getSingleton().createManual("indexTexture","General",Ogre::TextureType::TEX_TYPE_2D, 16, 16, 0, Ogre::PixelFormat::PF_BYTE_BGRA, Ogre::TU_DEFAULT); 

Ogre::HardwarePixelBufferSharedPtr pixelBuffer = indexTexture->getBuffer(); 
pixelBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL); 

const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock(); 
Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data); 

Ogre::uint8 counter = 0; 
for (size_t j = 0; j < 16; j++) { 
for(size_t i = 0; i < 16; i++) 
{  
     if(i==8 || i==7) { 
    *pDest++ = 3; // B 
    *pDest++ = 0; // G 
    *pDest++ = 0; // R 
    *pDest++ = 0; // A 
    } else { 
    *pDest++ = 1; // B 
    *pDest++ = 0; // G 
    *pDest++ = 0; // R 
    *pDest++ = 0; // A 
    } 
    counter++; 
} 
} 

pixelBuffer->unlock(); 

Così ora ho una texture che posso usare come un indice con alcuni valori aggiunti per il test, questi valori verranno popolati in fase di esecuzione facendo clic sul riquadro.

Ora per passare questa texture in tutto ho dovuto passarlo alla tecnica corretta e passare il mio materiale, questo è stato fatto nel modo seguente:

Ogre::MaterialPtr material = Ogre::MaterialPtr(Ogre::MaterialManager::getSingleton().getByName("PlainTexture")); 
float mapSize = 16; 
float tas = 2; 
material->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("mapSize",mapSize); 
material->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("tas",tas); 
material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("indexTexture");  

Questo passa due valori troppo, mapSize è la dimensione della mappa stessa in tessere (assumendo il suo quadrato) e tas come dimensione dell'atlante di trama (numero di quadrati di tessere differenti lungo la larghezza dell'atlante).

Per consentire il mio materiale per capire quello che ho appena passato in cui avevo bisogno di modificare un po 'il mio file di materiale come segue:

// CG Pixel shader definition 
fragment_program PlainTexture_PS cg    
{ 
    source GameObjStandard.cg  
    entry_point main_plain_texture_fp 
    profiles arbfp1 
default_params 
{ 
    param_named tas float 
    param_named 
}    
} 

E il mio passo è stato ridefinito un po' troppo

pass     
{ 
        // Make this pass use the vertex shader defined above 
    vertex_program_ref PlainTexture_VS  
    { 
    } 
        // Make this pass use the pixel shader defined above 
    fragment_program_ref PlainTexture_PS  
    { 
    } 
    texture_unit 0 
    { 
     filtering none   
    } 
texture_unit 1 
{ 
    texture textureatlas.png 2d 
    tex_address_mode clamp 
    filtering anisotropic 
} 
} 

Ho poi riscritto il programma cg texture framment per tenere conto dei cambiamenti che avevo fatto.

void main_plain_texture_fp(
    float2 uv0 : TEXCOORD0, // UV interpolated for current pixel 
    out float4 color : COLOR, // Output color we want to write 
uniform float tas, 
uniform float mapSize, 

    // Model Level Inputs 
    uniform sampler2D Tex0: TEXUNIT0, 
uniform sampler2D Tex1: TEXUNIT1) 
{ 
//get the index position by truncating the uv coordinates 
float2 flooredIndexes = floor(uv0); 

//get the colour of the index texture Tex0 at this floored coordinate 
float4 indexColour = tex2D(Tex0, ((1.0/mapSize) * flooredIndexes)+(0.5/mapSize)); 

//calculate the uv offset required for texture atlas range = 0 - 255 
float indexValue = (255 * indexColour.b) + (255 * indexColour.g) + (255 * indexColour.r); 

//float indexValue = (tas * tas) - indexValue0; 

if(indexValue < tas*tas) { 
    float row = floor(indexValue/tas); 
    float col = frac(indexValue/tas) * tas; 

    float uvFraction = 1.0/tas; 

    float uBase = col * uvFraction; 
    float vBase = 1 - ((tas - row) * uvFraction); 

    float uOffset = frac(uv0.x)/tas; 
    float vOffset = (frac(uv0.y))/tas; 

    float uNew = uBase + uOffset; 
    float vNew = vBase + vOffset; 

    float2 uvNew = {uNew, vNew}; 

    if(frac(uv0.x) > 0.99 || frac(uv0.x) < 0.01) { 
    float4 color1 = {1,1,1,0}; 
    color = (0.2*color1) + (0.8*tex2D(Tex1,uvNew)); 
    } else if(frac(uv0.y) > 0.99 || frac(uv0.y) < 0.01) { 
    float4 color1 = {1,1,1,0}; 
    color = (0.2*color1) + (0.8*tex2D(Tex1,uvNew)); 
    } else { 
    color = tex2D(Tex1,uvNew); 
    } 


} else { 
    float4 color2 = {0.0,0,0,0}; 
    color = color2; 
} 
} 

Questo calcola il texel corretto richiesto dalle atlante trama, si sovrappone anche una griglia debole sopra la parte superiore combinando 80% colore texel e nero 20%.

Se l'atlante struttura non ha l'indice del colore specificato dalla texture dell'indice poi appena uscite nero (Questo è principalmente quindi è molto facile da individuare.

Di seguito è riportato un esempio di output utilizzando un . 2 x 2 atlante struttura

enter image description here

+0

@TheSHEEEP Spero che questo ti aiuti/ti interessi. –

+0

Decisamente utile, grazie :) – TheSHEEEP

+0

@TheSHEEEP Nessun problema, anche nel caso ve lo stiate chiedendo, ho dimenticato di menzionare l'immagine renderizzata in basso non è in realtà proprio quello che si ottiene con il codice sopra. Il codice sopra pone una griglia semitrasparente sopra, l'immagine non tiene conto della trama sotto la griglia e la dipinge semplicemente di nero. –

Problemi correlati