Объяснение принципа работы openGL

Я пытаюсь понять, как работает кодирование в openGL. Я нашел этот код в Интернете, и я хочу понять это ясно.

Для моего вершинного шейдера у меня есть:

темя

uniform vec3 fvLightPosition;
    varying vec2 Texcoord;
    varying vec2 Texcoordcut;
    varying vec3 ViewDirection;
    varying vec3 LightDirection;
    uniform mat4 extra;

    attribute vec3 rm_Binormal;
    attribute vec3 rm_Tangent;

    uniform float fSinTime0_X;
    uniform float fCosTime0_X;

    void main( void )
    {
       gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex * extra;
       Texcoord    = gl_MultiTexCoord0.xy;
       Texcoordcut   = gl_MultiTexCoord0.xy;

       vec4 fvObjectPosition = gl_ModelViewMatrix * gl_Vertex;

       vec3 rotationLight = vec3(fCosTime0_X,0, fSinTime0_X);
       ViewDirection  =  - fvObjectPosition.xyz;
       LightDirection = (-rotationLight ) * (gl_NormalMatrix); 
    }

А для своего шейдера Fragment я создал белый цвет на изображении, чтобы создать в нем дыру.:

uniform vec4 fvAmbient;
uniform vec4 fvSpecular;
uniform vec4 fvDiffuse;
uniform float fSpecularPower;

uniform sampler2D baseMap;
uniform sampler2D bumpMap;

varying vec2 Texcoord;
varying vec2 Texcoordcut;
varying vec3 ViewDirection;
varying vec3 LightDirection;

void main( void )
{
   vec3  fvLightDirection = normalize( LightDirection );
   vec3  fvNormal         = normalize( ( texture2D( bumpMap, Texcoord ).xyz * 2.0 ) - 1.0 );
   float fNDotL           = dot( fvNormal, fvLightDirection ); 
   vec3  fvReflection     = normalize( ( ( 2.0 * fvNormal ) * fNDotL ) - fvLightDirection ); 
   vec3  fvViewDirection  = normalize( ViewDirection );
   float fRDotV           = max( 0.0, dot( fvReflection, fvViewDirection ) );
   vec4  fvBaseColor      = texture2D( baseMap, Texcoord );

   vec4  fvTotalAmbient   = fvAmbient * fvBaseColor; 
   vec4  fvTotalDiffuse   = fvDiffuse * fNDotL * fvBaseColor; 
   vec4  fvTotalSpecular  = fvSpecular * ( pow( fRDotV, fSpecularPower ) );


   if(fvBaseColor == vec4(1,1,1,1)){ 
      discard;
   }else{ 
     gl_FragColor = ( fvTotalDiffuse + fvTotalSpecular );
   }



}

Кто-нибудь, кто может объяснить мне все, что все делает? Я понимаю основную идею этого. Но не часто, зачем вам это нужно, и что происходит, когда вы используете другие переменные? То, что происходит, - то, что свет вокруг чайника прибывает и удаляется во времени. Как это правильно связано с косинусом и синусовыми переменными? Что если я захочу, чтобы свет исходил сверху и уходил на дно чайника?

Также,

  • Что означают эти строки?

    vec4 fvObjectPosition = gl_ModelViewMatrix * gl_Vertex;

  • И почему здесь минус перед переменной?

    ViewDirection = - fvObjectPosition.xyz;

  • Почему мы используем отрицательное вращение света?

    LightDirection = (-rotationLight) * (gl_NormalMatrix);

  • Почему они используют *2.0) - 1.0 для вычисления нормального вектора? Разве это невозможно при Normal = normalize (gl_NormalMatrix * gl_Normal);?

    vec3 fvNormal = normalize ((texture2D (bumpMap, Texcoord).xyz *2.0) - 1.0);

2 ответа

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

  1. Что означают эти строки? vec4 fvObjectPosition = gl_ModelViewMatrix * gl_Vertex;

    Это преобразует gl_Vertex (точки ребра многоугольника) из системы координат объекта / модели в систему координат камеры. Другими словами, он применяет все повороты и переводы ваших вершин. z ось - ось обзора камеры, указывающая на экран или с экрана и x,y оси такие же, как экраны. Никакие выступы / обрывы / зажимы не применяются!!! Полученная точка сохраняется в fvObjectPosition 4D вектор (x,y,z,w) Я настоятельно рекомендую вам прочитать " Понимание матриц однородного преобразования 4x4" и подссылки, на которые также стоит обратить внимание.

  2. И почему здесь минус перед переменной? ViewDirection = - fvObjectPosition.xyz;

    Скорее всего, потому что вам нужно направление от поверхности к камере, так direction_from_surface=camera_pos-surface_pos как твой surface_pos уже находится в системе координат камеры, то положение камеры в тех же координатах (0,0,0) так что результат direction_from_surface=(0,0,0)-surface_pos=-surface_pos или вы получили отрицательный Z направление обзора оси (зависит от формата ваших матриц). Трудно определить без справочной информации.

  3. Почему мы используем отрицательное вращение света? LightDirection = (-rotationLight ) * (gl_NormalMatrix);

    скорее всего по тем же причинам, что и пуля 2

  4. Почему они используют *2.0)-1.0 для расчета нормального вектора?

    Шейдер использует нормальное / рельефное отображение, что означает, что вы получили текстуру с нормальными векторами, закодированными как RGB. Как RGB текстуры зажаты в диапазоне <0,1> и нормальные координаты вектора находятся в диапазоне <-1,+1> тогда вам просто нужно перемасштабировать тексель

    • RGB*2.0 находится в диапазоне <0,2>
    • RGB*2.0-1.0 находится в диапазоне <-1,+1>

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

    • плоская поверхность имеет normal=(0.0,0.0,+1.0) так в RGB было бы (0.5,0.5,1.0)

    Это обычный голубовато-пурпурный цвет, часто встречающийся в текстурах (см. Ссылку выше).

    Но да, вы можете использовать Normal = normalize( gl_NormalMatrix * gl_Normal);

    Но это устранит карту неровностей и нормалей, и вы получите только плоские поверхности. Что-то вроде этого:

  5. Свет

    vec3(fCosTime0_X,0, fSinTime0_X) выглядит как направление света. Этот вращается вокруг y ось. Если вы хотите изменить направление света на что-то другое, просто сделайте его равномерным и передайте его непосредственно шейдеру вместо fCosTime0_X,fSinTime0_X

Как это правильно связано с косинусом и синусовыми переменными?

Вы можете отправлять данные в единую переменную шейдера с помощью функции glUniform. Например: в вашем вершинном шейдере у вас есть 2 значения с плавающей запятой, поэтому вы будете вызывать glUniform1f дважды каждый раз с другим местоположением и другим значением.
Или вы можете прикрепить переменные типа float к одной переменной vec2 следующим образом:
uniform vec2 fSinValues; и заполните их glUniform2f(location, sinVal, cosVal);

Что если я захочу, чтобы свет исходил сверху и уходил на дно чайника?

Если вы хотите, чтобы ваш свет вращался в другом направлении, просто передайте значения sin и cos в различные пространственные координаты прямо здесь: vec3 rotationLight = vec3(fCosTime0_X,fSinTime0_X, 0);

Другие вопросы по тегам