Объяснение принципа работы 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 ответа
Слишком лениво, чтобы полностью проанализировать код без точного контекста того, что вы отправляете шейдерам... но ваши подвопросы достаточно просты:
Что означают эти строки?
vec4 fvObjectPosition = gl_ModelViewMatrix * gl_Vertex;
Это преобразует
gl_Vertex
(точки ребра многоугольника) из системы координат объекта / модели в систему координат камеры. Другими словами, он применяет все повороты и переводы ваших вершин.z
ось - ось обзора камеры, указывающая на экран или с экрана иx,y
оси такие же, как экраны. Никакие выступы / обрывы / зажимы не применяются!!! Полученная точка сохраняется вfvObjectPosition
4D вектор(x,y,z,w)
Я настоятельно рекомендую вам прочитать " Понимание матриц однородного преобразования 4x4" и подссылки, на которые также стоит обратить внимание.И почему здесь минус перед переменной?
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
направление обзора оси (зависит от формата ваших матриц). Трудно определить без справочной информации.Почему мы используем отрицательное вращение света?
LightDirection = (-rotationLight ) * (gl_NormalMatrix);
скорее всего по тем же причинам, что и пуля 2
Почему они используют
*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);
Но это устранит карту неровностей и нормалей, и вы получите только плоские поверхности. Что-то вроде этого:
Свет
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);