Преобразование OpenGL из Directional/point в Spotlight

Итак, в настоящее время я работаю над созданием прожектора в своем вершинном шейдере, в настоящее время я могу создавать направленный и/или точечный свет, используя модель освещения Фонга.

Мне трудно рассчитать правильные углы для прожектора, в основном просто нужен прожектор, который исходит из 0,0,0 в пространстве глаза и смотрит вниз по координате Z.

Я пытаюсь просто сделать все (на данный момент) в конусе ярко-белым, а все за его пределами темным.

#version 130

uniform mat4 model_view_matrix;
uniform mat4 projection_matrix;
uniform mat3 normal_matrix;
uniform int light_mode;

uniform vec4 light_pos;
uniform vec3 light_ambient;
uniform vec3 light_diffuse;
uniform vec3 light_specular;

uniform vec3 mtl_ambient;
uniform vec3 mtl_diffuse;
uniform vec3 mtl_specular;
uniform float mtl_shininess;

// Spotlight test
const float spotCutOff = 100.00f;

in vec3 position;
in vec3 normal;
in vec2 texCoord;

out vec2 st;
out vec4 litColour;


vec3 phongLight(in vec4 position, in vec3 norm)
{
    // s is the direction from the light to the vertex
    vec3 s;
    if (light_pos.w == 0.0) {
        s = normalize(light_pos.xyz);
    }
    else {
        s = normalize(vec3(light_pos - position));
    }

    // v is the direction from the eye to the vertex
    vec3 v = normalize(-position.xyz);

    // r is the direction of light reflected from the vertex
    vec3 r = reflect(-s, norm);

    vec3 ambient = light_ambient * mtl_ambient;

    // The diffuse component
    float sDotN = max(dot(s,norm), 0.0);
    vec3 diffuse = light_diffuse * mtl_diffuse * sDotN;

    // Specular component
    vec3 spec = vec3(0.0);
    if (sDotN > 0.0)
        spec = light_specular * mtl_specular * pow(max(dot(r,v), 0.0), mtl_shininess);

    return ambient + diffuse + spec;
}

vec3 spotLight(in vec4 position, in vec3 norm)
{
    vec3 ambient = vec3(0.2, 0.2, 0.2);

    vec3 lightDir = normalize(vec3(light_pos - position));
    vec3 spotDir = vec3(0.0, 0.0, -1.0);



    float angle = degrees(acos(dot(spotDir, lightDir)));
    //angle = max (angle, 0);

    if ((angle) < spotCutOff) {
        return vec3(1.0, 1.0, 1.0);
    }

    float dist = sqrt(positon.x * position.x + position.y + position.y + position.z * position.z);

    if (dist < 1) {
        return vec3(1.0,1.0,0.0);
    }

    return vec3(0.2, 0.2, 0.2);
}

void main(void)
{
    // Convert normal and position to eye coords
    vec3 eyeNorm = normalize(normal_matrix * normal);
    vec4 eyePos = model_view_matrix * vec4(position, 1.0);

    // No lighting effect
    if (light_mode == 0)
    {
        litColour = vec4(1.0, 1.0, 1.0, 1.0);
    }
    // Directional overhead light
    else if (light_mode == 1)
    {
        litColour = vec4(phongLight(eyePos, eyeNorm), 1.0);
    }
    // Point light
    else if (light_mode == 2)
    {
        litColour = vec4(phongLight(eyePos, eyeNorm), 1.0);
    }
    else if (light_mode == 3)
    {
        litColour = vec4(spotLight(eyePos, eyeNorm), 1.0);
    }

    //litColour = vec4(normal*1000, 1.0);

    gl_Position = projection_matrix * eyePos;
    st = texCoord;
}

person supertro0per    schedule 08.05.2015    source источник


Ответы (1)


Ваш прожектор определяется позицией (ps) и направлением (ds). Таким образом, для каждой вершины в позиции vp вы можете вычислить d=vp-ps, нормализовать это до dn=normalize(d), а затем точка(dn,ds) даст вам угол в центре внимания. Просто масштабируйте его или сравните с отсечкой, чтобы получить скаляр!

В качестве альтернативы и в долгосрочной перспективе лучше думать о прожекторе как о камере. Сделайте то же самое, что и для своей камеры: модель и матрица вида! Преобразуйте каждую вершину в это пространство и спроецируйте ее из x, y, z, w в x, y, z. z — это расстояние, которое всегда полезно для освещения, а x, y вы можете использовать для поиска текстуры круглой формы (или любой другой).

При использовании обеих техник следует помнить об одном: обратная проекция: убедитесь, что свет направлен только вперед! Проверьте знак z или скалярное произведение!

person starmole    schedule 08.05.2015