GLSL: вращающийся нормальный

Есть сцена с некоторыми объектами и местностью. Когда я пытаюсь повернуть объект, нормали остаются прежними. Означает, что темная сторона объекта остается темной стороной объекта.
Моя зеркальная молния работает.

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

uniform vec3 lightPos;
uniform sampler2D Texture;
varying vec2 TexCoord;

varying vec3 position;
varying vec3 vertex;
varying mat3 nMat;
varying mat3 vMatrix;
varying vec3 normal;
varying vec3 oneNormal;
varying vec3 lightPos2;

void main()
{
gl_Position=gl_ModelViewProjectionMatrix*gl_Vertex;
position=vec3(gl_ModelViewMatrix*gl_Vertex);
vMatrix = mat3(gl_ModelViewMatrix);
lightPos2 = vec3(gl_ModelViewMatrix*vec4(lightPos,1.0));
vertex = vec3(gl_Vertex);
nMat = gl_NormalMatrix;
normal=gl_NormalMatrix*gl_Normal;
oneNormal = gl_Normal;
TexCoord=gl_MultiTexCoord0.xy;
}

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

varying vec3 position;
varying vec3 normal;

uniform sampler2D Texture;
varying vec2 TexCoord;

uniform vec3 lightPos;
varying vec3 vertex;
uniform vec3 lambient;
uniform vec3 ldiffuse;
uniform vec3 lspecular;
uniform float shininess;
varying mat3 nMat;
varying mat3 vMatrix;
varying vec3 oneNormal;
varying vec3 lightPos2;void main()
{
float dist=length(vertex-lightPos);
float att=1.0/(1.0+0.1*dist+0.01*dist*dist);
vec4 TexColor = texture2D(Texture, TexCoord);
vec3 ambient=TexColor.rgb*lambient; //the ambient light

//=== Diffuse ===//
vec3 surf2light=normalize(position-lightPos2);
float dcont=max(0.0,
dot( normalize(nMat*(-normal)), nMat*surf2light) );
vec3 diffuse=dcont*(TexColor.rgb*ldiffuse);

//=== Specular ===//
vec3 surf2view = normalize(lightPos-position);
surf2light=nMat*normalize(-vertex);
vec3 reflection=reflect(-surf2view,normalize(normal));

float scont=pow(max(0.0,dot(surf2light,reflection)),shininess);
vec3 specular=scont*lspecular;

gl_FragColor=vec4((ambient+diffuse+specular)*att,1.0);
}

-2

Решение

Вы трансформируете нормы. Но по крайней мере для части расчетов освещения вы используете положение источника света, которое также преобразуется в то же координатное пространство. Если вы преобразуете оба нормали а также источник света, направление нормали относительно источника света снова будет таким же.

Извлечение ключевых линий из вершинного шейдера:

    position=vec3(gl_ModelViewMatrix*gl_Vertex);
lightPos2 = vec3(gl_ModelViewMatrix*vec4(lightPos,1.0));
normal=gl_NormalMatrix*gl_Normal;

gl_NormalMatrix соответствует gl_ModelViewMatrix, с необходимыми настройками для преобразования векторов направления вместо точек. Поэтому преобразование вида модели было применено ко всем position, lightPos2 а также normal,

Затем все три из этих значений (с применением интерполяции) передаются в фрагментный шейдер, где у вас есть этот расчет для члена рассеянного освещения:

    vec3 surf2light=normalize(position-lightPos2);
float dcont=max(0.0,
dot( normalize(nMat*(-normal)), nMat*surf2light) );
vec3 diffuse=dcont*(TexColor.rgb*ldiffuse);

Теперь есть пара вопросов:

  • Вы подаете заявку nMat, которая является нормальной матрицей, снова к обоим векторам, даже если они уже были преобразованы. Это не вредит, так как скалярное произведение не меняется, если вы применяете одинаковое вращение к обоим векторам, но это не имеет смысла.
  • Все используемые значения (position, lightPos2, normal) были преобразованы матрицей вида модели. Таким образом, их относительные позиции / направления точно такие же, как они были изначально. Результат вычисления будет таким же, как если бы он был применен к соответствующим нетрансформированным векторам.

Вам необходимо решить, какую систему координат вы хотите использовать для расчетов освещения. Есть хотя бы пара вариантов. Самым простым для вас, вероятно, является использование координатного пространства глаза. Чтобы сделать это, вы можете применить преобразование вида к позиции источника света перед передачей его в шейдер, а затем использовать эту позицию источника света без дополнительных преобразований в коде шейдера.

Так как вы говорите, что зеркальное освещение работает как нужно, и вы используете униформу lightPos там, это может быть так же просто, как использовать эту переменную вместо lightPos2 в диффузном расчете.

0

Другие решения


По вопросам рекламы [email protected]