OpenGl display a 16 bit tramite Tao / C #
-
21-08-2019 - |
Domanda
Ho alcuni dati dell'immagine scientifici che sta venendo fuori da un dispositivo rilevatore in una gamma a 16 bit che poi viene reso in un'immagine. Per visualizzare questi dati, sto usando OpenGL, perché dovrebbe sostenere ushorts come parte della libreria. Sono riuscito a ottenere questi dati in trame di rendering su una piattaforma di 1,4 OpenGL, una limitazione che è un requisito di questo progetto.
Purtroppo, le texture risultanti sembrano stanno venendo ridotte a 8 bit, piuttosto che 16 bit. I test questa immagine generando un gradiente e la visualizzazione; mentre l'immagine stessa ha ogni pixel diverso dai suoi vicini, la struttura mostrata mostra modelli di striscia dove tutti i pixel affiancati vengono visualizzati come valori uguali.
Ho provato a fare questo con GlDrawPixels, e l'immagine risultante in realtà sembra che sia davvero il rendering tutti i 16 bit.
Come posso forzare queste texture per visualizzare correttamente?
Per dare più di fondo, la LUT (LookUp Table) è determinato dalla seguente codice:
String str = "!!ARBfp1.0\n" +
"ATTRIB tex = fragment.texcoord[0];\n" +
"PARAM cbias = program.local[0];\n" +
"PARAM cscale = program.local[1];\n" +
"OUTPUT cout = result.color;\n" +
"TEMP tmp;\n" +
"TXP tmp, tex, texture[0], 2D;\n" +
"SUB tmp, tmp, cbias;\n" +
"MUL cout, tmp, cscale;\n" +
"END";
Gl.glEnable(Gl.GL_FRAGMENT_PROGRAM_ARB);
Gl.glGenProgramsARB(1, out mFragProg);
Gl.glBindProgramARB(Gl.GL_FRAGMENT_PROGRAM_ARB, mFragProg);
System.Text.Encoding ascii = System.Text.Encoding.ASCII;
Byte[] encodedBytes = ascii.GetBytes(str);
Gl.glProgramStringARB(Gl.GL_FRAGMENT_PROGRAM_ARB, Gl.GL_PROGRAM_FORMAT_ASCII_ARB,
count, encodedBytes);
GetGLError("Shader");
Gl.glDisable(Gl.GL_FRAGMENT_PROGRAM_ARB);
Dove cbias e CSCALE sono compresi tra 0 e 1.
Grazie!
EDIT: Per rispondere ad alcune delle altre domande, la linea con glTexImage:
Gl.glBindTexture(Gl.GL_TEXTURE_2D, inTexData.TexName);
Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_LUMINANCE, inTexData.TexWidth, inTexData.TexHeight,
0, Gl.GL_LUMINANCE, Gl.GL_UNSIGNED_SHORT, theTexBuffer);
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR); // Linear Filtering
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR); // Linear Filtering
theTexBuffer = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Il formato di pixel è impostata quando il contesto è inizializzato:
Gdi.PIXELFORMATDESCRIPTOR pfd = new Gdi.PIXELFORMATDESCRIPTOR();// The pixel format descriptor
pfd.nSize = (short)Marshal.SizeOf(pfd); // Size of the pixel format descriptor
pfd.nVersion = 1; // Version number (always 1)
pfd.dwFlags = Gdi.PFD_DRAW_TO_WINDOW | // Format must support windowed mode
Gdi.PFD_SUPPORT_OPENGL | // Format must support OpenGL
Gdi.PFD_DOUBLEBUFFER; // Must support double buffering
pfd.iPixelType = (byte)Gdi.PFD_TYPE_RGBA; // Request an RGBA format
pfd.cColorBits = (byte)colorBits; // Select our color depth
pfd.cRedBits = 0; // Individual color bits ignored
pfd.cRedShift = 0;
pfd.cGreenBits = 0;
pfd.cGreenShift = 0;
pfd.cBlueBits = 0;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0; // No alpha buffer
pfd.cAlphaShift = 0; // Alpha shift bit ignored
pfd.cAccumBits = 0; // Accumulation buffer
pfd.cAccumRedBits = 0; // Individual accumulation bits ignored
pfd.cAccumGreenBits = 0;
pfd.cAccumBlueBits = 0;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = 16; // Z-buffer (depth buffer)
pfd.cStencilBits = 0; // No stencil buffer
pfd.cAuxBuffers = 0; // No auxiliary buffer
pfd.iLayerType = (byte)Gdi.PFD_MAIN_PLANE; // Main drawing layer
pfd.bReserved = 0; // Reserved
pfd.dwLayerMask = 0; // Layer masks ignored
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;
pixelFormat = Gdi.ChoosePixelFormat(mDC, ref pfd); // Attempt to find an appropriate pixel format
if (!Gdi.SetPixelFormat(mDC, pixelFormat, ref pfd))
{ // Are we not able to set the pixel format?
BigMessageBox.ShowMessage("Can not set the chosen PixelFormat. Chosen PixelFormat was " + pixelFormat + ".");
Environment.Exit(-1);
}
Soluzione
Se si crea una texture il parametro 'tipo' di glTexImage è digitare i dati i dati la struttura è in prima di essere convertito da OpenGL nel proprio formato. Per creare una texture a 16 bit per canale è necessario qualcosa come GL_LUMINANCE16 come formato (formato interno rimane GL_LUMINANCE). Se non c'è GL_LUMINANCE16 per OpenGL 1.4 controllo se GL_EXT_texture è disponibile e provare con GL_LUMINANCE16_EXT.
Una di queste dovrebbe funzionare. Tuttavia, se non è possibile codificare i valori a 16 bit come due coppie 8 bit con GL_LUMINANCE_ALPHA e decodificare di nuovo all'interno di uno shader.
Altri suggerimenti
Non ho mai lavorato in profondità maggiore (profondi) rispetto 8bit per canale, ma ecco cosa mi piacerebbe provare prima:
Spegnere il filtraggio sulla texture e vedere come influisce l'uscita.
glHints Set texturing per la migliore qualità.
Si potrebbe considerare l'utilizzo di un solo canale in virgola mobile tessitura attraverso uno dei GL_ARB_texture_float
, GL_ATI_texture_float
o GL_NV_float_buffer
estensioni se l'hardware lo supporta, non riesco a ricordare se GL 1.4 ha le texture in virgola mobile o no però .