返回

OpenGL ES for Android:点光源、聚光灯和阳光的多重光照效果

Android

在学习过光照、材质、投光物之后,我们把这些效果结合起来。我们显示这样的效果:在阳光照射下,有几个点光源,同时有一个聚光灯,此时在不同位置的物体被光照的效果。

定向光的计算可以参考前面的章节,这里不再赘述。

需要注意的是,在传入点光源的数据时,传入的参数名需要以:pointLight..作为前缀,传入的参数名需要以:spotLight..作为前缀。

struct PointLight {
    vec3 position;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float constant;
    float linear;
    float quadratic;
};

struct SpotLight {
    vec3 position;
    vec3 direction;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float constant;
    float linear;
    float quadratic;
    float cutOff;
    float outerCutOff;
};

// ...

void setPointLight(int index, const PointLight& light) {
    char name[16];
    sprintf(name, "pointLights[%d]", index);
    glUniform3fv(glGetUniformLocation(program, name), 1, &light.position[0]);
    sprintf(name, "pointLights[%d].ambient", index);
    glUniform3fv(glGetUniformLocation(program, name), 1, &light.ambient[0]);
    sprintf(name, "pointLights[%d].diffuse", index);
    glUniform3fv(glGetUniformLocation(program, name), 1, &light.diffuse[0]);
    sprintf(name, "pointLights[%d].specular", index);
    glUniform3fv(glGetUniformLocation(program, name), 1, &light.specular[0]);
    sprintf(name, "pointLights[%d].constant", index);
    glUniform1f(glGetUniformLocation(program, name), light.constant);
    sprintf(name, "pointLights[%d].linear", index);
    glUniform1f(glGetUniformLocation(program, name), light.linear);
    sprintf(name, "pointLights[%d].quadratic", index);
    glUniform1f(glGetUniformLocation(program, name), light.quadratic);
}

// ...

void setSpotLight(int index, const SpotLight& light) {
    char name[16];
    sprintf(name, "spotLights[%d]", index);
    glUniform3fv(glGetUniformLocation(program, name), 1, &light.position[0]);
    sprintf(name, "spotLights[%d].direction", index);
    glUniform3fv(glGetUniformLocation(program, name), 1, &light.direction[0]);
    sprintf(name, "spotLights[%d].ambient", index);
    glUniform3fv(glGetUniformLocation(program, name), 1, &light.ambient[0]);
    sprintf(name, "spotLights[%d].diffuse", index);
    glUniform3fv(glGetUniformLocation(program, name), 1, &light.diffuse[0]);
    sprintf(name, "spotLights[%d].specular", index);
    glUniform3fv(glGetUniformLocation(program, name), 1, &light.specular[0]);
    sprintf(name, "spotLights[%d].constant", index);
    glUniform1f(glGetUniformLocation(program, name), light.constant);
    sprintf(name, "spotLights[%d].linear", index);
    glUniform1f(glGetUniformLocation(program, name), light.linear);
    sprintf(name, "spotLights[%d].quadratic", index);
    glUniform1f(glGetUniformLocation(program, name), light.quadratic);
    sprintf(name, "spotLights[%d].cutOff", index);
    glUniform1f(glGetUniformLocation(program, name), light.cutOff);
    sprintf(name, "spotLights[%d].outerCutOff", index);
    glUniform1f(glGetUniformLocation(program, name), light.outerCutOff);
}

// ...

// 以下为示例代码,您需要根据自己的实际场景进行调整。

PointLight pointLights[4] = {
    {
        vec3(0.0f, 1.0f, 0.0f),
        vec3(0.1f, 0.1f, 0.1f),
        vec3(1.0f, 1.0f, 1.0f),
        vec3(1.0f, 1.0f, 1.0f),
        1.0f,
        0.09f,
        0.032f
    },
    {
        vec3(2.0f, 3.0f, -4.0f),
        vec3(0.1f, 0.1f, 0.1f),
        vec3(1.0f, 1.0f, 1.0f),
        vec3(1.0f, 1.0f, 1.0f),
        1.0f,
        0.09f,
        0.032f
    },
    {
        vec3(-2.0f, 3.0f, -4.0f),
        vec3(0.1f, 0.1f, 0.1f),
        vec3(1.0f, 1.0f, 1.0f),
        vec3(1.0f, 1.0f, 1.0f),
        1.0f,
        0.09f,
        0.032f
    },
    {
        vec3(0.0f, 3.0f, 4.0f),
        vec3(0.1f, 0.1f, 0.1f),
        vec3(1.0f, 1.0f, 1.0f),
        vec3(1.0f, 1.0f, 1.0f),
        1.0f,
        0.09f,
        0.032f
    }
};

SpotLight spotLight = {
    vec3(0.0f, 5.0f, 0.0f),
    vec3(0.0f, -1.0f, 0.0f),
    vec3(0.1f, 0.1f, 0.1f),
    vec3(1.0f, 1.0f, 1.0f),
    vec3(1.0f, 1.0f, 1.0f),
    1.0f,
    0.09f,
    0.032f,
    cos(radians(12.5f)),
    cos(radians(17.5f))
};

// ...

for (int i = 0; i < 4; i++) {
    setPointLight(i, pointLights[i]);
}

setSpotLight(0, spotLight);

通过上述代码,您将能够在您的 Android 项目中实现点光源、聚光灯和阳光的多重光照效果。

我希望这个教程对您有所帮助。如果您有任何问题,请随时提出。