Как реализовать плоское затенение в LWJGL с индексным и вершинным буферами? - PullRequest
2 голосов
/ 02 февраля 2020

В настоящее время я разрабатываю программу, которая отображает здания и рельеф в 3D в Java фреймворке LWJGL, который, как я понимаю, очень похож на OpenGL. Я пытаюсь различить стороны зданий, используя плоскую штриховку. Например, куб, сгенерированный моей программой, должен выглядеть так:

enter image description here

Чтобы добиться этого, я попытался реализовать метод здесь: https://gamedev.stackexchange.com/questions/152991/how-can-i-calculate-normals-using-a-vertex-and-index-buffer.

Кажется, это затенение вершин, которое окрашивает каждый пиксель в своего рода градиент. Моя реализация в настоящее время выглядит так:

enter image description here

Очевидно, это не похоже на то, что я хотел. Вот мои вершинные и фрагментные шейдеры:

#version 150

in vec3 position;
in vec2 textureCoordinates;
in vec3 normal;

out vec2 pass_textureCoordinates;
out vec3 surfaceNormal;
out vec3 toLightVector;
out vec3 toCameraVector;

uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;

void main(void){

    vec4 worldPosition = transformationMatrix * vec4(position, 1.0);

    gl_Position = projectionMatrix * viewMatrix * worldPosition;
    pass_textureCoordinates = textureCoordinates;

    surfaceNormal = (transformationMatrix * vec4(normal, 0.0)).xyz;
    toLightVector = lightPosition - worldPosition.xyz;
    toCameraVector = (inverse(viewMatrix) * vec4(0.0,0.0,0.0,1.0)).xyz - worldPosition.xyz;

}
#version 150

in vec2 pass_textureCoordinates;
in vec3 surfaceNormal;
in vec3 toLightVector;
in vec3 toCameraVector;

out vec4 out_Color;

uniform sampler2D modelTexture;
uniform vec3 lightColour;
uniform float shineDamper;
uniform float reflectivity;

void main(void){

    vec3 unitNormal = normalize(surfaceNormal);
    vec3 unitLightVector = normalize(toLightVector);

    float nDotl = dot(unitNormal, unitLightVector);
    float brightness = max(nDotl, 0.7);
    vec3 diffuse = brightness * lightColour;

    vec3 unitVectorToCamera = normalize(toCameraVector);
    vec3 lightDirection = -unitLightVector;
    vec3 reflectedLightDirection = reflect(lightDirection, unitNormal);

    float specularFactor = dot(reflectedLightDirection, unitVectorToCamera);
    specularFactor = max(specularFactor, 0.0);
    float dampedFactor = pow(specularFactor, shineDamper);
    vec3 finalSpecular = dampedFactor * reflectivity * lightColour;


    out_Color = vec4(diffuse, 1.0) * texture(modelTexture,pass_textureCoordinates) + vec4(finalSpecular, 1.0);

}

Если здание в форме куба, которое я пытаюсь визуализировать, индексируется так: enter image description here

Как программно создать массив нормалей для плоского затенения?

1 Ответ

0 голосов
/ 02 февраля 2020

«Вид градиента» вызван Зеркальными бликами . Если векторы нормалей нормальны к граням куба, то рассеянный по Ламберту свет даст вам плоский вид.
Все, что вам нужно сделать, это инициализировать единую переменную reflectivity на 0,0 , (на самом деле это значение по умолчанию).


Возможно вычисление векторов нормалей лица по частным производным (dFdx, dFdy) в шейдере фрагмента или по кросс-произведению в геометрическом шейдере. Но эта опция приведет к потере качества и скорости.

См.
Из фрагмента шейдера как получить поверхность - не вершина - нормальная
3D-объект окрашен таким образом, что выглядит как 2D-объект

...