2014-10-16 4 views
0

У меня есть short текстуру, которую я хочу читать в шейдере, WebGL не поддерживает short текстур, так что я расколоть короткие два байта и отправить его в шейдер:Короткие текстуры WebGL

var ushortValue = reinterval(i16Value, -32768, 32767, 0, 65535); 

textureData[j*4] = ushortValue & 0xFF; // first byte 
ushortValue = ushortValue >> 8; 
textureData[j*4+1] = ushortValue & 0xFF; // second byte 
textureData[j*4+2] = 0; 
textureData[j*4+3] = 0; 

А потом я загрузить данные в графической карты:

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, textureData); 

в пиксельный шейдер:

vec4 valueInRGBA = texture2D(ctTexture, xy)*255.0; // range 0-1 to 0-255 
float real_value = valueInRGBA.r + valueInRGBA.g*256; 
real_value = reinterval(real_value , 0.0, 65535.0, 0.0, 1.0); 
gl_FragColor = vec4(real_value, real_value, real_value, 1.0); 

Но я потерял разрешение по сравнению с тем, когда я загружаю короткие данные в обычный opengl, который поддерживает короткие текстуры. Может ли кто-нибудь увидеть, что я делаю неправильно?

enter image description here

Вот еще одна странность разные я получаю от WebGL и OpenGL, с теми же данными. Я рисую значение как выше, я получаю одинаковые цвета, но я мало меньше разрешения. А затем добавить две строки:

ct_value = reinterval(ct_value, 0.0, 65535.0, -32768.0, 32767.0); 
ct_value = reintervalClamped(ct_value, -275.0, 475.0, 0.0, 1.0); 
gl_FragColor = vec4(ct_value,ct_value,ct_value,1.0); 

В OPENGL все выглядит хорошо, но в WebGL все становится белым с точным и тот же код.

OPENGL: enter image description here WebGL: enter image description here

+1

Не следует умножать в шейдере на 255.0 (2^8-1) вместо 254.0? – BDL

+0

или даже * 256 *, потому что 'ushortValue = ushortValue >> 8;' делятся на –

+0

Я изменил его, спасибо, но все же разрешение все еще плохо – hidayat

ответ

0

Я решать те же проблемы, и она отлично работает для меня. Моя реализация в дротике, но она похожа. У меня есть 2 возможных решения:

1) Использование поплавка текстуры

gl.getExtension("OES_texture_float") 
texture format = GL.LUMINANCE 
texture data type = GL.FLOAT 

maxValue = (signed)?32767.0:65535.0; 
textureData = new Float32List(width*height); 
for (int i=0;i<size;i++) { 
    textureData[i] = data[i]/maxValue; 
} 

Это решение прекрасно работает, и нет необходимости выполнять какие-либо специальные вычисления в шейдере, но вам нужно расширение OES_float_linear использовать линейную текстуру интерполяции и текущая версия Chrome не поддерживает ее.

2) Используйте раствор с хранящим коротким значением для RGB

pixels = new Uint8List(width*height*3); 
for (int i=0;i<width*height;i++) { 
    int val = (signed)?data[i].abs():data[i]; 
    textureData[i*3] = val&0xFF; 
    textureData[i*3+1] = val>>8; 
    textureData[i*3+2] = (signed && data[i]<0)?255:0; 
} 

И стоимость реконструкции в шейдер:

float tval = texture2D(imageTex, vUv).r/256.0+texture2D(imageTex, vUv).g; 
if (texture2D(imageTex, vUv).b>0.0) tval = -tval 

Но это решение имеет один большой вопрос, при увеличении масштаба и есть GL .LINEAR-фильтрация позволяет отображать плохие данные на краях с высокой степенью контрастности изображения, потому что байт красного и зеленого цветов интерполируется отдельно.

Заключение: Оба решения работают, но ни одна из них не может использоваться с линейной интерполяцией текстуры. Возможно, можно выполнить ручную интерполяцию в флеш-шейдере.

Смежные вопросы