3

So I've currently managed to write a shader using Xoppa tutorials and use an AssetManager, and I managed to bind a texture to the model, and it looks fine.

[MyExample[1

Now the next step I guess would be to create diffuse(not sure if thats the word? phong shading?) lighting(?) to give the bunny some form of shading. While I have a little bit of experience with GLSL shaders in LWJGL, I'm unsure how to process that same information so I can use it in libGDX and in the glsl shaders.

I understand that this all could be accomplished using the Environment class etc. But I want to achieve this through the shaders alone or by traditional means simply for the challenge.

In LWJGL, shaders would have uniforms:

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;

This would be reasonably easy for me to calculate in LWJGL

Vertex file:

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);
}

I imagine that I could implement the uniforms similarly to the LWGL glsl example, but I dont know how I can apply these uniforms into libgdx and have it work. I am unsure what u_projViewTrans is, I'm assuming it is a combination of the projection, transformation and view matrix, and setting the uniform with the camera.combined?

If someone could help me understand the process or point to an example of how (per pixel lighting?), can be implemented with just the u_projViewTrans and u_worldTrans, I'd greatly appreciate your time and effort in helping me understand these concepts a bit better.

Heres my github upload of my work in progress.here

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
winnieTheWind
  • 141
  • 12
  • It is helpful but its still a little confusing cause it isnt utilizing libgdx. Thanks a lot though. I found a github page showing shader tests in libgdx here https://github.com/libgdx/libgdx/tree/master/tests/gdx-tests-android/assets/data/g3d/shaders – winnieTheWind Oct 01 '17 at 11:39
  • My apologies, it probably would help if I studied those links you shared. – winnieTheWind Oct 01 '17 at 11:46

1 Answers1

3

You can do the light calculations in world space. A simple lambertian diffuse light can be calculated like this:

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

A detailed explanation can be found in the answer to the Stackoverflow question How does this faking the light work on aerotwist?.

While Gouraud shading calculates the light in the the vertex shader, Phong shading calculates the light in the fragment shader.
(see further GLSL fixed function fragment program replacement)


A Gouraud shader may look like this:

Vertex 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 );
}


A Phong shading may look like this:

Vertex Shader:

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 );
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Thanks for sharing! I'm gonna try and implement this and I'll post my progress. – winnieTheWind Oct 01 '17 at 11:48
  • Amazing, it worked! Is there any way I can control the light position uniform in libgdx? I see that there is a PointLight class that takes in a vec3 position. Would that have anything to do with it?. Thanks again. – winnieTheWind Oct 02 '17 at 04:19
  • I tried out your phong shader above...I tried it out but I accidentally put the wrong code in which shader, so I swapped it. it runs but I only see black. I'm assuming its something im not implementing properly, possibly the uniform variable. If I apply a 'setUniformi("u_pointLights, 0)', it prints an error saying no uniform can be found. I'm guessing there is a way to link your pointLight to the class PointLight but I'm unsure how to do so. Thanks again. – winnieTheWind Oct 02 '17 at 13:42