16-битный дисплей OpenGl через Tao/C#
-
21-08-2019 - |
Вопрос
У меня есть некоторые научные данные изображения, которые поступают из детекторного устройства в 16-битном диапазоне и затем преобразуются в изображение.Чтобы отобразить эти данные, я использую OpenGL, поскольку он должен поддерживать ushorts как часть библиотеки.Мне удалось перенести эти данные в рендеринг текстур на платформе OpenGL 1.4 — ограничение, которое является требованием этого проекта.
К сожалению, полученные текстуры выглядят так, будто их уменьшили до 8 бит, а не до 16 бит.Я проверяю это, создавая градиентное изображение и отображая его;хотя в самом изображении каждый пиксель отличается от соседних, отображаемая текстура представляет собой полосатый рисунок, в котором все пиксели, расположенные рядом друг с другом, отображаются как равные значения.
Я попробовал сделать это с помощью GlDrawPixels, и полученное изображение на самом деле выглядит так, как будто оно действительно отображает все 16 бит.
Как заставить эти текстуры отображаться правильно?
Чтобы дать больше информации, LUT (таблица поиска) определяется следующим кодом:
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);
Где cbias и cScale находятся в диапазоне от 0 до 1.
Спасибо!
РЕДАКТИРОВАТЬ:Чтобы ответить на некоторые другие вопросы, строка с 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();
Формат пикселей устанавливается при инициализации контекста:
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);
}
Решение
Если вы создаете текстуру, параметр 'type' glTexImage - это только тип данных, в котором находятся ваши данные текстуры, прежде чем они будут преобразованы OpenGL в свой собственный формат.Чтобы создать текстуру с 16 битами на канал, вам понадобится что-то вроде GL_LUMINANCE16 в качестве формата (внутренний формат остается GL_LUMINANCE).Если для OpenGL 1.4 нет GL_LUMINANCE16, проверьте, доступна ли GL_EXT_texture, и попробуйте ее с GL_LUMINANCE16_EXT.
Один из них должен сработать.Однако если это не так, вы можете закодировать свои 16-битные значения как две 8-битные пары с помощью GL_LUMINANCE_ALPHA и снова декодировать их внутри шейдера.
Другие советы
Я никогда не работал с глубиной выше (глубже), чем 8 бит на канал, но вот что я бы попробовал в первую очередь:
Отключите фильтрацию текстуры и посмотрите, как это повлияет на результат.
Установите текстурирование glHints на лучшее качество.
Вы можете рассмотреть возможность использования одноканальной текстуры с плавающей запятой через один из GL_ARB_texture_float
, GL_ATI_texture_float
или GL_NV_float_buffer
расширения, если оборудование их поддерживает, но я не могу вспомнить, есть ли в GL 1.4 текстуры с плавающей запятой или нет.