2012-04-23 3 views
2

Я работаю над OpenGL ES fluid simulation, который использует текстурные карты для хранения значений сетки. Мне нужно перебирать через сетку, которая имитирует следующий цикл:Интерполированные координаты текстуры

for (int r = 0; r < 128; r++) 
    for (int c = 0; c < 128; c++) 
     process grid element at (c,r) 

Повторить через сетку я просто заполнив четырехугольник, который вызывает мою программу фрагмент, который будет вызван для каждого фрагмента. Координаты текстуры (0,0), (1,0), (0,1), (1,1) связаны с вершинами (-1, -1), (+ 1, -1), (- 1, + 1), (+ 1, + 1), и я сделать четверной (как треугольник полоса) в карту в 128х128 текстуры, прикрепленной к FBO следующим образом:

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, texFrameBuffer); 
glViewport(0, 0, TEX_IMAGE_WIDTH, TEX_IMAGE_HEIGHT); // 128 x 128 

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 
glEnableVertexAttribArray(positionAttr); 
glVertexAttribPointer(positionAttr, 2, GL_FLOAT, GL_FALSE, 0, 0); 

glBindBuffer(GL_ARRAY_BUFFER, texCoordBuffer); 
glEnableVertexAttribArray(texCoordAttr); 
glVertexAttribPointer(texCoordAttr, 2, GL_FLOAT, GL_FALSE, 0, 0); 

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

вершина шейдер просто проходит положение и текстурные координаты через немодифицированные. Чтобы понять, какая текстурная координата генерируется, я решил зафиксировать координаты текстуры в изображении. Программа фрагмент присваивает его дал 2D координаты текстуры с красными и зелеными каналов выходного цвета:

varying vec4 texCoord; 
void main() { 
    gl_FragColor = vec4(texCoord.st,0,1); 
} 

Затем я использую glGetTexImage() прочитать текстуру обратно в клиентское пространство. Ниже приведены образцы сгенерированных координат текстуры (S, T) для каждого пикселя в изображении:

(column, row) = [s, t] -> (128*s, 128*t) 

(0,0) = [0.00392157, 0.00392157] -> (0,0) 
(1,0) = [0.01176471, 0.00392157] -> (1,0) 
(2,0) = [0.01960784, 0.00392157] -> (2,0) 
(3,0) = [0.02745098, 0.00392157] -> (3,0) 
(4,0) = [0.03529412, 0.00392157] -> (4,0) 
(5,0) = [0.04313726, 0.00392157] -> (5,0) 
(6,0) = [0.05098040, 0.00392157] -> (6,0) 
(7,0) = [0.05882353, 0.00392157] -> (7,0) 
(8,0) = [0.06666667, 0.00392157] -> (8,0) 
(9,0) = [0.07450981, 0.00392157] -> (9,0) 
(10,0) = [0.08235294, 0.00392157] -> (10,0) 
<snip> 
(125,0) = [0.98039222, 0.00392157] -> (125,0) 
(126,0) = [0.98823535, 0.00392157] -> (126,0) 
(127,0) = [0.99607849, 0.00392157] -> (127,0) 
(0,1) = [0.00392157, 0.01176471] -> (0,1) 
(1,1) = [0.01176471, 0.01176471] -> (1,1) 
(2,1) = [0.01960784, 0.01176471] -> (2,1) 
<snip> 
(124,127) = [0.97254908, 0.99607849] -> (124,127) 
(125,127) = [0.98039222, 0.99607849] -> (125,127) 
(126,127) = [0.98823535, 0.99607849] -> (126,127) 
(127,127) = [0.99607849, 0.99607849] -> (127,127) 

Теперь к вопросу. Я пытаюсь понять эти сгенерированные координаты. Волшебное значение 0.00392157: (0.5 * 1/127.5). Я понимаю фактор 0.5, который действует округленное значение, которое предварительно добавлено, но почему 127.5? (0.5 * 1/128.0) будет иметь больше смысла? Может ли кто-нибудь объяснить эти координаты? Я просто хочу генерировать целые координаты сетки из координат текстуры (нет sampler2Drect в OpenGL ES).

ответ

3

Я всегда с этим сталкиваюсь, поэтому давайте посмотрим, смогу ли я это объяснить.

Представьте себе один ряд вашей сетки. На следующем рисунке я пронумеровал каждый из фрагментов (0-127) в этой строке. Я добавил некоторые текстурные координаты ниже пикселей. Обратите внимание, что крайний левый край равен 0.0, а самый правый край - 1.0.

+-----------+-----------+-----------+-----------+--- ---+-----------+ 
|   |   |   |   |   |   | 
|   |   |   |   |   |   | 
|  0  |  1  |  2  |  3  | . . . | 127 | 
|   |   |   |   |   |   | 
|   |   |   |   |   |   | 
+-----------+-----------+-----------+-----------+--- ---+-----------+ 
^   ^  ^  ^     ^  ^
|   |   |   |      |   | 
|   |   |   |      |   | 
0/128  1/128  2/128  3/128    127/128  128/128 

Когда рендер хочет текстурировать фрагмент, он использует координаты текстуры на центра фрагмента - где число есть. Обратите внимание, что центр фрагмента 0 находится на полпути между 0/128 (aka 0) и 1/128 (aka .0078125). Это 1/256 (ака .00390625).

Таким образом, я думаю, что формула будет лучше выражена как:

coordinate = (pixelId + 0.5)/128 

Вот некоторые питона, который получает ВАРИАНТЫ ОТВЕТА подобные к вашему:

for i in range(128): 
    print (0.5 + i)/128 


0.00390625 
0.01171875 
0.01953125 
0.02734375 
0.03515625 
0.04296875 
... 
0.97265625 
0.98046875 
0.98828125 
0.99609375 

Я подозреваю, что разница между моими результатами и ваши результаты связаны с тем, что ваши значения были сжаты в один [8-бит] цветной канал, чтобы вернуть их из шейдера.

Надеюсь, это поможет.

+0

Не могли бы вы прояснить предложение: «Представьте себе 128 строк вашей сетки». пожалуйста? –

+0

спасибо, @JohnFisher. Я исправил свое искаженное предложение. – certainmagic

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