Скрипт шейдера Love2d GLSL не может получить переменную texture_coords

Всем привет! Я пытался написать скрипт, использующий GLSL для рендеринга множества Мандельброта, но происходит что-то странное.

Я называю эффект functio следующим образом:

vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords){

Но когда я пытаюсь использовать значения texture_coords, скажем, так:

vec2 c = vec2((texture_coords[0]-WD/2)/100, (texture_coords[1]-HT/2)/100);

Он возвращает одно и то же значение для каждого пикселя; если, с другой стороны, вместо этого я использую screen_coords, это работает, но я боюсь, что если я перетащу окно вокруг него, это может привести к искажению результатов.

Почему я не могу получить texture_coords?

Больше информации о программе и проблемах -fract">здесь


ОБНОВИТЬ

Я переработал код, теперь он выглядит так:

vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 window_coords)
{

    vec2 c = vec2( ( MinRe + window_coords[0] * ( MaxRe - MinRe ) / ( width + 1 ) ),
                   ( MaxIm - window_coords[1] * ( MaxIm - MinIm ) / ( height + 1 ) )
    );

    vec2 z = c;
    vec2 zn = vec2(0.0, 0.0);

    int n_iter = 0;

    while( (z[0]*z[0] + z[1]*z[1] < 4) && (n_iter < max_iter)) {
      zn[0] = z[0]*z[0] - z[1]*z[1] + c[0];
      zn[1] = 2* z[0]*z[1] + c[1];

      z[0] = zn[0];
      z[1] = zn[1];
      n_iter++;
}

Который прекрасно работает. Но когда я использую texture_coords вместо window_coords, код возвращает одно и то же значение для каждого пикселя, несмотря на то, что используемая текстура имеет тот же размер окна.


person Vitu Tomaz    schedule 08.01.2016    source источник
comment
screen_coords назван неправильно; настоящее имя будет window_coords.   -  person Nicol Bolas    schedule 08.01.2016
comment
Значит, он получает координаты относительно окна, верно? А что такое texture_coords?   -  person Vitu Tomaz    schedule 08.01.2016
comment
Вы знаете, у Love2D есть вики.   -  person Nicol Bolas    schedule 08.01.2016
comment
Вики говорит, что на самом деле это координаты относительно экрана....   -  person Vitu Tomaz    schedule 08.01.2016
comment
Да. Это те же люди, которые назвали их screen_coords. Конечно, они думают, что это относительно экрана. Я хочу сказать, что это дает вам определение того, что означает texture_coords.   -  person Nicol Bolas    schedule 08.01.2016
comment
Но это несколько ошибочно, потому что моя текстура была размером с окно, и она не работала, поэтому я подумал, что определение может быть неправильным.   -  person Vitu Tomaz    schedule 08.01.2016


Ответы (2)


Проблема в том, что некоторые рисуемые объекты love.graphics не устанавливают координаты текстуры, если вы не загружаете изображение. Итак, вместо использования draw.rectangle вы должны использовать Mesh:

Двухмерная полигональная сетка, используемая для рисования произвольных текстурированных фигур.

Чтобы добавить объект сетки, вы можете добавить к функции загрузки:

function love.load()
    width, height = love.graphics.getDimensions( )
    local vertices = {
        {
            -- top-left corner 
            0, 0, -- position of the vertex
            0, 0, -- texture coordinate at the vertex position
            255, 0, 0, -- color of the vertex
        },
        {
            -- top-right corner 
            width, 0,
            1, 0, -- texture coordinates are in the range of [0, 1]
            0, 255, 0
        },
        {
            -- bottom-right corner 
            width, height,
            1, 1,
            0, 0, 255
        },
        {
            -- bottom-left corner 
            0, height,
            0, 1,
            255, 255, 0
        },
    }

    -- the Mesh DrawMode "fan" works well for 4-vertex Meshes.
    mesh = love.graphics.newMesh(vertices, "fan")

    -- ... other stuff here ...

end

и в функции рисования:

function love.draw()
    -- ...
    love.graphics.draw(mesh,0,0)
    -- ...
end

Полный код, учитывая ваш предыдущий вопрос и мой ответ на него, добавив несколько строк для управления преобразованиями координат, станет следующим:

function love.load()
    width, height = love.graphics.getDimensions( )
    local vertices = {
        {
            -- top-left corner 
            0, 0, -- position of the vertex
            0, 0, -- texture coordinate at the vertex position
            255, 0, 0, -- color of the vertex
        },
        {
            -- top-right corner 
            width, 0,
            1, 0, -- texture coordinates are in the range of [0, 1]
            0, 255, 0
        },
        {
            -- bottom-right corner 
            width, height,
            1, 1,
            0, 0, 255
        },
        {
            -- bottom-left corner 
            0, height,
            0, 1,
            255, 255, 0
        },
    }

    mesh = love.graphics.newMesh(vertices, "fan")

    GLSLShader = love.graphics.newShader[[
        vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
        vec4 white = vec4(1.0, 1.0, 1.0, 1.0);
        extern int max_iter;
        extern vec2 size;
        extern vec2 left_top;

        vec4 clr(int n){
            if(n == max_iter){return black;}

            float m = float(n)/float(max_iter);
            float r = float(mod(n,256))/32;
            float g = float(128 - mod(n+64,127))/255;
            float b = float(127 + mod(n,64))/255;

            if (r > 1.0) {r = 1.0;}
            else{ 
                if(r<0){r = 0;}
            }

            if (g > 1.0) {g = 1.0;}
            else{
                if(g<0){g = 0;}
            }

            if (b > 1.0) {b = 1.0;}
            else{
                if(b<0){b = 0;}
            }
            return vec4(r, g, b, 1.0);
        }

        vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 window_coords){  

            vec2 c = vec2(texture_coords[0]*size[0] + left_top[0],texture_coords[1]*size[1] - left_top[1]);
            vec2 z = vec2(0.0,0.0);
            vec2 zn = vec2(0.0,0.0);
            int n_iter = 0;
            while ( (z[0]*z[0] + z[1]*z[1] < 4) &&  (n_iter < max_iter) ) {
                zn[0] = z[0]*z[0] - z[1]*z[1] + c[0];
                zn[1] = 2*z[0]*z[1] + c[1];
                z[0] = zn[0];
                z[1] = zn[1];
                n_iter++;
            }
            return clr(n_iter);
        }
    ]]

end

function love.draw()

    center_x = -0.5
    center_y = 0.0
    size_x = 3
    size_y = size_x*height/width
    GLSLShader:send("left_top",{center_x-size_x*0.5,center_y+size_y*0.5})
    GLSLShader:send("size",{size_x,size_y})
    GLSLShader:sendInt("max_iter",1024)

    love.graphics.setShader(GLSLShader)
    love.graphics.draw(mesh,0,0)
    love.graphics.setShader()
end
person Bob__    schedule 08.01.2016

Но это несколько ошибочно, потому что моя текстура была размером с окно, и это не сработало.

Что ж, давайте исследуем это. Вы не совсем точно предоставили много информации, но давайте все же посмотрим.

(texture_coords[0]-WD/2)/100

Что это? Что ж, мы знаем, что такое texture_coords. Из вики Love2D:

Местоположение внутри текстуры, из которого нужно получить данные о пикселях. Координаты текстуры обычно нормализуются в диапазоне от (0, 0) до (1, 1), при этом верхний левый угол равен (0, 0).

Таким образом, вы вычитаете из этой координаты текстуры WD/2. Вы не удосужились упомянуть, что это за значение WD. Но независимо от того, вы делите результат на 100.

Итак, что такое WD? Посмотрим, поможет ли алгебра:

val = (texture_coords[0]-WD/2)/100
val * 100 = texture_coords[0] - WD / 2
(val * 100) - texture_coords[0] = -WD / 2
-2 * ((val * 100) - texture_coords[0]) = WD

Итак, что такое WD? Ну, из этого уравнения я могу определить... ничего. Это уравнение кажется тарабарщиной.

Я предполагаю, что вы хотите, чтобы WD означало «ширину» (серьезно, это еще три символа; вы не могли напечатать это?). Предположительно, ширина текстуры. Если это так... уравнение остается бессмысленным.

Вы берете значение в диапазоне от [0, 1], а затем вычитаете из него половину ширины текстуры. Что это обозначает? Зачем делить на 100? Поскольку ширина текстуры, вероятно, намного больше, чем наибольшее значение из texture_coords (он же: 1), результатом этого будет в основном -WD/200.

И если вы не визуализируете изображение с плавающей запятой, оно будет ограничено допустимым цветовым диапазоном: [0, 1]. Таким образом, все ваши значения будут одного цвета: черного.

Поскольку вы говорите о Мандельброте и так далее, я подозреваю, что вы пытаетесь сгенерировать значения в диапазоне [-1, 1] или где-то еще. И ваше уравнение могло бы сделать это... если бы texture_coords не были нормализованными координатами текстуры в диапазоне [0, 1]. Вы знаете, именно так, как говорит Вики.

Если вы хотите преобразовать координаты текстуры в диапазон [-1, 1], это действительно намного проще. Вот почему мы используем нормализованные координаты текстуры:

vec2 c = (2 * texture_coord) - 1; //Vector math is good.

Если вы хотите, чтобы это был диапазон [-100, 100], просто умножьте результат на 100.

person Nicol Bolas    schedule 08.01.2016
comment
Извините, я не предоставил достаточно информации... Я новичок на форуме и пытаюсь понять, как правильно написать сообщение. В моем последнем мне сказали предоставить меньше кода, я вижу, что на этот раз я предоставил не только мало кода, но и почти недостаточно информации. Код, который я предоставил, был более поздней пробной версией, но я ранее пробовал его так (texture_coords[0]-WD/2/100), но это не помогло... Я также новичок в программировании, и у меня очень мало знаний о правильной практике кодирования... В любом случае, спасибо за помощь, я постараюсь быть более точным в своем будущем кодировании :) - person Vitu Tomaz; 08.01.2016
comment
Моя общая точка зрения заключалась в том, что ширина не имеет значения. Ширина уже учтена. Неважно, насколько большой или маленький вы нарисуете четырехугольник; координата текстуры по-прежнему будет меняться от 0 вверху/слева до 1 внизу/справа. - person Nicol Bolas; 08.01.2016
comment
Я сделал обновление поста. Я полностью переработал код, но с texture_coords он все равно ведет себя странно... - person Vitu Tomaz; 08.01.2016
comment
Чувак, я действительно ценю помощь, но тебе действительно не нужно было быть таким грубым... Я прекрасно понимаю эти концепции, и если ты проверишь обновление, я заставил его работать с screen_coords, что теоретически то же самое. . И если вы проверите ответ Bob__, проблема в том, как работают чертежи, а не в моей логике. - person Vitu Tomaz; 10.01.2016
comment
Я заставил его работать с screen_coords, что теоретически то же самое. Это не одно и то же. Именно это я и пытаюсь донести до вас. Верхняя правая часть вашего четырехугольника будет иметь координату окна (ширина, 0). Но координата текстуры будет (1, 0). Вот что значит нормализация. - person Nicol Bolas; 10.01.2016
comment
Хорошо, я дважды проверил вики, и теперь я понимаю, что вы имели в виду. Извините за недопонимание, но я действительно думаю, что вы могли бы быть немного более вежливым. Спасибо вам за помощь - person Vitu Tomaz; 10.01.2016