2012-07-01 12 views
6

Estoy usando Ogre3D como motor de gráficos.¿Estoy haciendo algo mal con este programa de CG?

creo una malla de forma manual, que funciona bien, UV son correctos y se establecen para representar las coordenadas de cuadrícula (para este ejemplo la red se encuentra a 10 x 10)

que no hacer nada en el programa de vértices y tienen una muy programa de fragmento simple. He incluido ambos programas más el archivo de material para explicar.

Mi problema es que, incluso con el filtro establecido como ninguno, los colores no parecen ser los mismos que mi imagen original (esto es solo una imagen de prueba que estoy usando porque estaba teniendo problemas para crear la textura manualmente ogro). Resulta que el problema no es mi código en ogro, sino más bien algo relacionado con el archivo de material o los programas fragmento/vértice.

También he incluido una captura de pantalla de la salida a la izquierda y la imagen original a la derecha. El sombreador de fragmentos también dibuja una cuadrícula simple sobre la parte superior para poder asegurarme de que las coordenadas uv se pasen correctamente. Lo que parecen ser.

enter image description here

Cualquier idea sería muy apreciada ya que estoy realmente seguro de lo que estoy haciendo mal.

archivo Material:

// 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 del archivo:

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

gracias para la edición, no estaba seguro de cómo poner imágenes en :) –

+0

cambiando 'float4 indexColour = tex2D (Tex0, (1,0/10) * flooredIndexes);' a ' float4 indexColour = tex2D (Tex0, (1.0/20) * flooredIndexes); 'puede resolver el problema – hamed

+0

No estoy seguro si eso ayudó o no, no resolvió el problema. La razón por la que estaba multiplicando por 1/10 es porque los índices en uv0 actualmente se ejecutan de 0 a 10 en la dirección u y v. Piso este valor porque está interpolado en el programa de fragmentos, así que obtengo valores como 5.6, si piso este valor, obtengo 5, que dividido por el número de mosaicos (10) me da la coordenada uv que necesito, 0.5 –

Respuesta

6

Ok por lo que ha sido un tiempo desde que he encontrado la solución a mis problemas por desgracia no estado en línea por lo que espero que esto ayude a temas similares .

Al crear cualquier textura que siempre debe hacer texturas un tamaño en texels 2^n * 2^m donde m y n son el ancho y la altura de la textura. Este fue mi primer error, aunque no me di cuenta en ese momento.

La razón por la que no había visto esto era porque mi atlas de textura principal se basaba en este principio y tenía una textura de 1024 x 1024. Lo que no había tenido en cuenta era el tamaño de la textura que estaba creando como índice de textura. Como mi mapa era 10 x 10, estaba creando una textura de 10 x 10 para los índices, supongo que se estiró de alguna manera (no estoy seguro de cómo funciona en el back-end) para ser 16 x 16 u 8 x 8, mezclando el texels juntos como lo hizo.

Lo primero que me dio la pista fue cuando escale mi lienzo en photoshop y encontré que los colores mezclados que estaba creando eran los mismos que los que obtenía en mi salida de ogre3d.

De todos modos pasar ..

Una vez que había averiguado esto pude crear la textura en Ogre y pasarlo a través de la siguiente

//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(); 

así que ahora tengo una textura que pueda usar como un índice con algunos valores que agregué para la prueba, estos valores eventualmente se completarán en el tiempo de ejecución haciendo clic en el mosaico.

Ahora a pasar esta textura a través tuve que pasarlo a la técnica correcta y pasar en mi materiales, esto se hizo de la siguiente manera:

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");  

Esto pasa dos valores también, mapSize siendo el tamaño del propio mapa en mosaicos (asumiendo que es un cuadrado) y tas siendo el tamaño del atlas de textura (número de cuadrados de textura diferentes en el ancho del atlas).

para permitir que mi material a entender lo que acaba de pasar en la que tenía que modificar mi archivo de material ligeramente de la siguiente manera:

// 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 
}    
} 

Y mi pase se redefinió un poco demasiado

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 
} 
} 

que luego reescribió el programa de fragmento de textura cg para tener en cuenta los cambios que había realizado.

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; 
} 
} 

Este calcula el texel correcta necesaria a partir de los atlas de textura, sino que también se superpone a una rejilla débil sobre la parte superior mediante la combinación de 80% de color Texel y 20% blanco.

Si el atlas de textura no tiene el índice del color especificado por la textura índice de entonces, sólo se da salida a negro (Esto es principalmente así que es muy fácil de detectar.

A continuación se muestra un ejemplo de la salida utilizando una . 2 x 2 atlas textura

enter image description here

+0

@ THESHEEEP Espero que esto te ayude o te interese. –

+0

Definitivamente útil, gracias :) – TheSHEEEP

+0

@ THESHEEEP No hay problema, también en caso de que se lo pregunte, olvidé mencionar que la imagen representada en la parte inferior no es exactamente lo que obtiene con el código anterior. El código anterior coloca una rejilla blanca semi transparente arriba, la imagen no tiene en cuenta la textura debajo de la grilla y solo la pinta en negro. –

Cuestiones relacionadas