Войти
ПрограммированиеФорумГрафика

Нюансы в примере “Использование рендеринга в текстуру для получения отражений с эффектами” с сайта steps3d.narod.ru

#0
10:39, 4 авг. 2017

Здравствуйте участники форума

Изучаю реализации отражений в DirectX и OpenGl

Наткнулся на статью http://steps3d.narod.ru/tutorials/render-reflection-tutorial.html с сайта steps3d.narod.ru

Покопавшись и реализовав предложенную технику отражения у себя, не до конца понял как она работает

В частности возникли вопросы к следующему фрагменту текста из статьи:
“Как известно произведение модельной и проектирующей матриц в OpenGL переводит всю сцену в куб [-1,1]^3”  вызывает недопонимание : чтобы перейти в упомянутый куб нужно координаты вершины, преобразованной данными матрицами, поделить на координату W, ведь так?

Далее в примере говорится об "отображение отрезка [-1,1] в отрезок [0,1]". В моем понимании отображение [-1,1] в [0,1] нужно осуществлять после деления на W, а в примере данное отображение [-1,1] в [0,1] осуществляется до деления на W и это работает. Почему нужно делать так?

Т. е. в статье делается так

//фрагмент кода на С++

glMatrixMode  ( GL_TEXTURE );
glPushMatrix  ();
glLoadIdentity ();
glTranslatef   ( 0.5, 0.5, 0 );
glScalef       ( 0.5, 0.5, 1 );
glMultMatrixf  ( pr );
glMultMatrixf  ( mv );

//фрагмент шейдера

texture2DProj ( reflectionMap, tex )

и это дает верный результат

Но я бы делaл так

//фрагмент кода на С++

glMatrixMode  ( GL_TEXTURE );
glPushMatrix  ();
glLoadIdentity ();
glMultMatrixf  ( pr );
glMultMatrixf  ( mv );

//фрагмент шейдера

tex = tex / tex.w  
tex.x = tex.x*0.5 + 0.5;
tex.y = tex.y*0.5 + 0.5;
texture2D ( reflectionMap, tex.xy )

и это дает НЕверный результат

Почему верен первый способ?

Надеюсь на ваше понимание моего вопроса и скорейшего ответа на него


#1
11:57, 4 авг. 2017

Насчет [-1,1]^3 вы правы - это действительно в NDC, т.е. после перспективного деления.
Умножение на матрицу масштабирования можно менять местами с перспектвным делением.
На самом деле если вы посмотрите умножение матрицы переноса на (x, y, z, w), то будет видно, что это тоже можно менять местами с перспекетвиным делением.
Так что ваш фрагмент шейдера выглядит верно, но это только фрагмент.
Вы умножаете tex на матрицы преобразования текстурных координат ?
Лучше укажите полные вершинный и фрамгентный шейдеры.
Я вечером посмотрю

#2
15:36, 4 авг. 2017

Нашел ошибку у себя, все заработало

Отражение | Нюансы в примере “Использование рендеринга в текстуру для получения отражений с эффектами” с сайта steps3d.narod.ru

Вершинный шейдер

varying vec3 pos;

uniform mat4x4 modelMatrix;

void main(void)
{
    pos = vec4(modelMatrix * vec4(gl_Vertex.xyz, 1)).xyz;

    gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1);
}

Фрамгентный шейдер

varying vec3 pos;

uniform sampler2D reflection;
uniform mat4x4 textureMatrix;

void main (void)
{
    vec4 tex2       = textureMatrix * vec4(pos, 1);

    vec2 tex3       = tex2.xy/tex2.w;
           
    vec2 tex4       = (tex3.xy*0.5)+vec2(0.5,0.5);

    vec3 reflColor = vec4(texture2D( reflection, tex4 )).xyz;

    gl_FragColor = vec4 ( reflColor, 1.0 );
}

Осталось еще пару вопросов.

В примере вы пишите что "получившаяся таким образом текстура не может быть наложена на отражающую грань обычным образом". Я не совсем понимаю что вы подразумеваете под обычным способом.

И еще не совсем понятно про инверсию перспективного преобразования:  "Подобное проектирование текстуры как бы инвертирует перспективное преобразование и в результате своего применения дает полностью корректное изображение отраженной сцены."

Про аналогию с проектором , который проецирует текстуру с отражением сцены понятно. Не понятна инверсия перспективного преобразования

#3
16:06, 4 авг. 2017

Обычным - с использованием обычных текстурных координат, текстурные координаты надо расчитывать приведленным способом
Я хотел сказать, что когда делали рендеринг в текстуру при этом уже было сделано перспективное преобразование и его надо учитывать при наложении текстуры.
Фактически этод метод наложения текстуры называется projective texturing, он очень близок к shadow mapping, только там мы не накладываем текстуру, а проивзодим сравнение.

#4
9:06, 5 авг. 2017

Для рендеринга отражения мы вычисляем текстурные координаты во фрагментном шейдере. Это принципиально? Мы это делаем что бы учитывать перспективу?

Ведь мы их(текстурные координаты) можем целиком вычислить в вершинном шейдере и вычисленные координаты будут интерполироваться ( z3*(t1/z1*(1-t)+t2/z2*t) ) вдоль треугольника при рендеренге и передаваться во фрагментный шейдер и потом использоваться для выборки из reflectionMap. Фрагментный шейдер будет состоять из одной строчки

gl_FragColor = texture2D( reflection, tex )

Вершинный шейдер

varying vec2 tex4;

uniform mat4x4 modelMatrix;
uniform mat4x4 textureMatrix;

void main(void)
{
    vec3 pos = vec4(modelMatrix * vec4(gl_Vertex.xyz, 1)).xyz;
    
    vec4 tex2       = textureMatrix * vec4(pos, 1);

    vec2 tex3       = tex2.xy/tex2.w;
           
    tex4       = (tex3.xy*0.5)+vec2(0.5,0.5);

    gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1);
}

Фрамгентный шейдер

varying vec2 tex4;

uniform sampler2D reflection;

void main (void)
{
   
    gl_FragColor = texture2D( reflection, tex4 );
}
Так можно делать?

Или мы можем вычислить vec4 = textureMatrix * modelMatrix * gl_Vertex в вершинном шейдере, графический конвейер будет интерполировать результат предыдущего вычисления и передавать результат интерполяции во фрагментный шейдер, далее мы сделаем во фрагментном шейдере перспективное деление, переведем  [-1,1] в [0,1]  и выберем по полученным значениям из  reflectionMap.

Вершинный шейдер

varying vec4 tex2;

uniform mat4x4 modelMatrix;
uniform mat4x4 textureMatrix;

void main(void)
{
    vec3 pos = vec4(modelMatrix * vec4(gl_Vertex.xyz, 1)).xyz;
    
    tex2       = textureMatrix * vec4(pos, 1);

    gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1);
}

Фрамгентный шейдер

varying vec4 tex2;

uniform sampler2D reflection;

void main (void)
{

    vec2 tex3       = tex2.xy/tex2.w;
           
    vec2 tex4       = (tex3.xy*0.5)+vec2(0.5,0.5);
   
    gl_FragColor = texture2D( reflection, tex4 );
}
Такой вариант возможен ?
ПрограммированиеФорумГрафика

Тема в архиве.