OpenGl visor 16 bits através Tao / C #
-
21-08-2019 - |
Pergunta
Eu tenho alguns dados de imagem científicas que está saindo de um dispositivo detector em uma faixa de 16 bits que então é renderizado em uma imagem. Para exibir esses dados, eu estou usando OpenGL, porque ele deve apoiar ushorts como parte da biblioteca. Eu consegui obter esses dados em texturas de renderização em um 1,4 plataforma OpenGL, uma limitação que é uma exigência do projeto.
Infelizmente, as texturas resultantes parecem que estão sendo reduzida para 8 bits, em vez de 16 bits. I testar esta através da geração de uma imagem de gradiente e exibi-lo; enquanto a própria imagem tem cada pixel diferente de seus vizinhos, a textura exibida está mostrando padrões de listras, onde todos os pixels ao lado do outro estão aparecendo como valores iguais.
Eu tentei fazer isso com glDrawPixels, ea imagem resultante, na verdade, parece que está realmente prestando todos os 16 bits.
Como posso forçar essas texturas para exibir corretamente?
Para dar mais fundo, a LUT (consulta à tabela) está a ser determinada pelo seguinte código:
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);
Onde cbias e CSCALE estão entre 0 e 1.
Obrigado!
EDIT: Para responder a algumas das outras questões, a linha com 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();
O formato de pixel é definido quando o contexto é inicializado:
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);
}
Solução
Se você criar uma textura do parâmetro 'tipo' de glTexImage é apenas os dados digite seus dados de textura está em antes de ser convertido por OpenGL em seu próprio formato. Para criar uma textura com 16 bits por canal que você precisa de algo como GL_LUMINANCE16 como o formato (formato interno restos GL_LUMINANCE). Se não houver GL_LUMINANCE16 para OpenGL 1.4 seleção se GL_EXT_texture está disponível e experimentá-lo com GL_LUMINANCE16_EXT.
Um destes deve funcionar. No entanto, se não você pode codificar seus valores de 16 bits como dois pares 8 bits com GL_LUMINANCE_ALPHA e decodificá-lo novamente dentro de um shader.
Outras dicas
Eu nunca trabalhei em profundidades maiores (mais profunda) do que 8 bits por canal, mas aqui está o que eu tentaria primeiro:
Desligue a filtragem da textura e ver como isso afeta a saída.
Definir texturização glHints a melhor qualidade.
Você poderia considerar o uso de um único canal de textura de ponto flutuante através de um dos GL_ARB_texture_float
, GL_ATI_texture_float
ou GL_NV_float_buffer
extensões se os suportes de hardware de TI, não me lembro se GL 1.4 tem texturas de ponto flutuante ou não embora.