OpenGL pantalla de 16 bits a través de Tao / C #
-
21-08-2019 - |
Pregunta
Tengo algunos datos de imágenes científicas que va a salir de un dispositivo detector en un rango de 16 bits que luego se hizo en una imagen. Con el fin de mostrar estos datos, estoy usando OpenGL, ya que debe soportar ushorts como parte de la biblioteca. Me las he arreglado para obtener estos datos en representación texturas en una plataforma de 1.4 OpenGL, una limitación que es un requisito de este proyecto.
Por desgracia, las texturas resultantes se ven como que están siendo reducidos a 8 bits, en lugar de 16 bits. I probar esta mediante la generación de una imagen de gradiente y la visualización de ella; mientras que la imagen en sí tiene cada píxel diferente de sus vecinos, la textura que se muestra está mostrando patrones de rayas en donde todos los píxeles de una al lado de otra están apareciendo como valores iguales.
He intentado hacer esto con GlDrawPixels, y la imagen resultante en realidad parece que está realmente haciendo todos los 16 bits.
¿Cómo puedo forzar estas texturas para mostrar correctamente?
Para dar más antecedentes, el LUT (tabla de búsqueda) se determina por el código siguiente:
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);
Donde cbias y CSCALE están entre 0 y 1.
Gracias!
EDIT: Para responder a algunas de las otras preguntas, la línea 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();
El formato de píxel se establece cuando se inicializa el contexto:
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);
}
Solución
Si crea una textura el parámetro 'tipo' de glTexImage es sólo el tipo de datos los datos de textura es de antes de que se convierte mediante OpenGL en su propio formato. Para crear una textura con 16 bits por canal se necesita algo así como GL_LUMINANCE16 como el formato (formato interno permanece GL_LUMINANCE). Si no hay GL_LUMINANCE16 para OpenGL 1.4 de verificación si GL_EXT_texture está disponible y tratar con GL_LUMINANCE16_EXT.
Uno de ellos debería funcionar. Sin embargo si no se puede codificar sus valores de 16 bits como dos pares de 8 bits con GL_LUMINANCE_ALPHA y decodificar de nuevo dentro de un shader.
Otros consejos
Nunca he trabajado en profundidades mayores (más profundas) que 8 bits por canal, pero esto es lo que me gustaría probar primero:
Desactivar el filtrado de la textura y ver cómo afecta a la salida.
glHints Conjunto de texturizado a mejor calidad.
Se podría considerar el uso de un único canal de punto flotante a través de la textura uno de los GL_ARB_texture_float
, GL_ATI_texture_float
o GL_NV_float_buffer
extensiones si el hardware lo soporta, no puedo recordar si GL 1.4 tiene texturas de punto flotante o no, aunque .