如何在LIBGDX的着色器中加入每像素照明?

时间:2017-10-01 11:14:13

标签: opengl 3d libgdx shader light

所以我目前设法使用Xoppa教程编写着色器并使用AssetManager,我设法将纹理绑定到模型,它看起来很好。

[MyExample [1

现在下一步我想是创建漫反射(不确定是否这个词?phong着色?)照明(?)给兔子一些形式的阴影。虽然我对LWJGL中的GLSL着色器有一点经验,但我不确定如何处理相同的信息,因此我可以在libGDX和glsl着色器中使用它。

我知道这一切都可以使用环境类等完成。但我想通过单独的着色器或仅通过传统方式来实现这一目标。

在LWJGL中,着色器会有制服:

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

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

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

这对我来说相当容易在LWJGL中计算

顶点文件:

attribute vec3 a_position;
attribute vec3 a_normal;
attribute vec2 a_texCoord0;

uniform mat4 u_worldTrans;
uniform mat4 u_projViewTrans;

varying vec2 v_texCoords;

void main() {
    v_texCoords = a_texCoord0;
    gl_Position = u_projViewTrans * u_worldTrans * vec4(a_position, 1.0);
}

我想我可以像LWGL glsl示例那样实现制服,但我不知道如何将这些制服应用到libgdx并让它工作。我不确定u_projViewTrans是什么,我假设它是投影,变换和视图矩阵的组合,并使用camera.combined设置制服?

如果有人可以帮助我理解这个过程或指向一个如何(每像素点亮?)的例子,只用u_projViewTrans和u_worldTrans来实现,我非常感谢你花时间和精力来帮助我理解这些概念好一点。

继承我正在进行的工作的github上传。here

1 个答案:

答案 0 :(得分:2)

您可以在世界空间中进行灯光计算。一个简单的lambertian diffuse灯可以这样计算:

vec3  toLightVector = normalize( lightPosition - vertexPosition );
float ligtIntensity = max( 0.0, dot( normal, toLightVector ));

详细解释可以在Stackoverflow问题How does this faking the light work on aerotwist?的答案中找到。

Gouraud shading计算顶点着色器中的灯光时,Phong shading会计算片段着色器中的灯光。
(进一步参见GLSL fixed function fragment program replacement


Gouraud shader可能如下所示:

顶点着色器:

attribute vec3 a_position;
attribute vec3 a_normal;
attribute vec2 a_texCoord0;

uniform mat4 u_worldTrans;
uniform mat4 u_projViewTrans;
uniform vec3 lightPosition;

varying vec2  v_texCoords;
varying float v_lightIntensity;

void main()
{
    vec4 vertPos       = u_worldTrans * vec4(a_position, 1.0);
    vec3 normal        = normalize(mat3(u_worldTrans) * a_normal);
    vec3 toLightVector = normalize(lightPosition - vertPos.xyz);
    v_lightIntensity   = max( 0.0, dot(normal, toLightVector));
    v_texCoords        = a_texCoord0;
    gl_Position        = u_projViewTrans * vertPos;
}

Fragment Shader:

varying vec2  v_texCoords;
varying float v_lightIntensity;

uniform sampler2D u_texture;

void main()
{
    vec4 texCol  = texture( u_texture, v_texCoords.st );
    gl_FragColor = vec4( texCol.rgb * v_lightIntensity, 1.0 );
}


Phong shading可能如下所示:

顶点着色器:

attribute vec3 a_position;
attribute vec3 a_normal;
attribute vec2 a_texCoord0;

uniform mat4 u_worldTrans;
uniform mat4 u_projViewTrans;

varying vec2 v_texCoords;
varying vec3 v_vertPosWorld;
varying vec3 v_vertNVWorld;

void main()
{
    vec4 vertPos   = u_worldTrans * vec4(a_position, 1.0);
    v_vertPosWorld = vertPos.xyz;
    v_vertNVWorld  = normalize(mat3(u_worldTrans) * a_normal);
    v_texCoords    = a_texCoord0;
    gl_Position    = u_projViewTrans * vertPos;
}

Fragment Shader:

varying vec2 v_texCoords;
varying vec3 v_vertPosWorld;
varying vec3 v_vertNVWorld;

uniform sampler2D u_texture;

struct PointLight
{
    vec3 color;
    vec3 position;
    float intensity;
};
uniform PointLight u_pointLights[1];

void main()
{
    vec3  toLightVector  = normalize(u_pointLights[0].position - v_vertPosWorld.xyz);
    float lightIntensity = max( 0.0, dot(v_vertNVWorld, toLightVector));
    vec4  texCol         = texture( u_texture, v_texCoords.st );
    vec3  finalCol       = texCol.rgb * lightIntensity * u_pointLights[0].color;
    gl_FragColor         = vec4( finalCol.rgb * lightIntensity, 1.0 );
}