Directional lighting is not constant in OpenGL ES 2.0/3.0 - android

Problem: The direction of the directional light changes when the position of the object changes.
I watched posts with a similar problem:
Directional light in worldSpace is dependent on viewMatrix
OpenGL directional light shader
Diffuse lighting for a moving object
Based on these posts, I tried to apply this:
#version 300 es
uniform mat4 u_mvMatrix;
uniform mat4 u_vMatrix;
in vec4 a_position;
in vec3 a_normal;
const vec3 lightDirection = vec3(-1.9, 0.0, -5.0);
...
void main() {
vec3 modelViewNormal = vec3(u_mvMatrix * vec4(a_normal, 0.0));
vec3 lightVector = lightDirection * mat3(u_vMatrix);
float diffuseFactor = max(dot(modelViewNormal, -lightVector), 0.0);
...
}
But the result looks like this:
Tried also:
vec3 modelViewVertex = vec3(u_mvMatrix * a_position);
vec3 lightVector = normalize(lightDirection - modelViewVertex);
float diffuseFactor = max(dot(modelViewNormal, lightVector), 0.0);
And:
vec3 lightVector = normalize(lightDirection - modelViewVertex);
lightVector = lightVector * mat3(u_vMatrix);
But the result:
What changes need to be made to the code so that all objects are lit identically?
Thanks in advance!
Solution:
In practice, creating directional lighting was not such an easy task for me. On Rabbid76 advice, I changed the order of multiplication. On another Rabbid76 advice (post), I also created a custom point of view:
Matrix.setLookAtM(pointViewMatrix, rmOffset:0, eyeX:3.8f, eyeY:0.0f, eyeZ:2.8f,
centerX:0.0f, centerY:0f, centerZ:0f, upX:0f, upY:1.0f, upZ:0.0f)
Also calculated eye coordinates and light vector, although the camera is set in [0, 0, 0]:
#version 300 es
uniform mat4 u_mvMatrix;
uniform mat4 u_pointViewMatrix;
in vec4 a_position;
in vec3 a_normal;
const vec3 lightPosition = vec3(-5.0, 0.0, 1.0);
...
void main() {
// transform normal orientation into eye space
vec3 modelViewNormal = vec3(u_mvMatrix * vec4(a_normal, 0.0));
vec3 modelViewVertex = vec3(u_mvMatrix * a_position); // eye coordinates
vec3 lightVector = normalize(lightPosition - modelViewVertex);
lightVector = mat3(u_pointViewMatrix) * lightVector;
float diffuseFactor = max(dot(modelViewNormal, lightVector), 0.0);
...
}
Only after these steps did the picture become good:
Small differences are probably caused by a big perspective.

The vector has to be multiplied to the matrix from the right. See GLSL Programming/Vector and Matrix Operations.
vec3 lightVector = lightDirection * mat3(u_vMatrix);
vec3 lightVector = mat3(u_vMatrix) * lightDirection;
If you want to dot the light calculations in view space, then the normal vecotr has to be transformed form object (model) space to view space by the model view matrix and the light direction hss to be transformed form world space to view space, by the view matrix. For instance:
void main() {
vec3 modelViewNormal = mat3(u_mvMatrix) * a_normal;
vec3 lightVector = mat3(u_vMatrix) * lightDirection;
float diffuseFactor = max(dot(modelViewNormal, -lightVector), 0.0);
// [...]
}

Related

opengl-es pre pixel lighting issue

there is a problem that i just can't seem to get a handle on..
i have a fragment shader:
precision mediump float;
uniform vec3 u_AmbientColor;
uniform vec3 u_LightPos;
uniform float u_Attenuation_Constant;
uniform float u_Attenuation_Linear;
uniform float u_Attenuation_Quadradic;
uniform vec3 u_LightColor;
varying vec3 v_Normal;
varying vec3 v_fragPos;
vec4 fix(vec3 v);
void main() {
vec3 color = vec3(1.0,1.0,1.0);
vec3 vectorToLight = u_LightPos - v_fragPos;
float distance = length(vectorToLight);
vec3 direction = vectorToLight / distance;
float attenuation = 1.0/(u_Attenuation_Constant +
u_Attenuation_Linear * distance + u_Attenuation_Quadradic * distance * distance);
vec3 diffuse = u_LightColor * attenuation * max(normalize(v_Normal) * direction,0.0);
vec3 d = u_AmbientColor + diffuse;
gl_FragColor = fix(color * d);
}
vec4 fix(vec3 v){
float r = min(1.0,max(0.0,v.r));
float g = min(1.0,max(0.0,v.g));
float b = min(1.0,max(0.0,v.b));
return vec4(r,g,b,1.0);
}
i've been following some tutorial i found on the web,
anyways, the ambientColor and lightColor uniforms are (0.2,0.2,0.2), and (1.0,1.0,1.0)
respectively. the v_Normal is calculated at the vertex shader using the
inverted transposed matrix of the model-view matrix.
the v_fragPos is the model result of multiplying the position with the normal model-view matrix.
now, i expect that when i move the light position closer to the cube i render, it will just appear brighter, but the resulting image is very different:
(the little square there is an indicator for the light position)
now, i just don't understand how this can happen?
i mean, i multiply the color components each by the SAME value..
so, how is it that it seems to vary so??
EDIT: i noticed that if i move the camera in front of the cube, the light is just shades of blue.. which is the same problem but maybe it's a clue i don't know..
The Lambertian reflectance is computed with the Dot product of the normal vector and the vector to the light source, instead of the component wise product.
See How does the calculation of the light model work in a shader program?
Use the dot function instead of the * (multiplication) operator:
vec3 diffuse = u_LightColor * attenuation * max(normalize(v_Normal) * direction,0.0);
vec3 diffuse = u_LightColor * attenuation * max(dot(normalize(v_Normal), direction), 0.0);
You can simplify the code in the fix function. min and max can be substituted with clamp. This functions work component wise, so they do not have to be called separately for each component:
vec4 fix(vec3 v)
{
return vec4(clamp(v, 0.0, 1.0), 1.0);
}

Anisotropic lighting in OpenGL ES 2.0/3.0. Black artifacts

I am trying to implement anisotropic lighting.
Vertex shader:
#version 300 es
uniform mat4 u_mvMatrix;
uniform mat4 u_vMatrix;
in vec4 a_position;
in vec3 a_normal;
...
out lowp float v_DiffuseIntensity;
out lowp float v_SpecularIntensity;
const vec3 lightPosition = vec3(-1.0, 0.0, 5.0);
const lowp vec3 grainDirection = vec3(15.0, 2.8, -1.0);
const vec3 eye_positiion = vec3(0.0, 0.0, 0.0);
void main() {
// transform normal orientation into eye space
vec3 modelViewNormal = mat3(u_mvMatrix) * a_normal;
vec3 modelViewVertex = vec3(u_mvMatrix * a_position);
vec3 lightVector = normalize(lightPosition - modelViewVertex);
lightVector = mat3(u_vMatrix) * lightVector;
vec3 normalGrain = cross(modelViewNormal, grainDirection);
vec3 tangent = normalize(cross(normalGrain, modelViewNormal));
float LdotT = dot(tangent, normalize(lightVector));
float VdotT = dot(tangent, normalize(mat3(u_mvMatrix) * eye_position));
float NdotL = sqrt(1.0 - pow(LdotT, 2.0));
float VdotR = NdotL * sqrt(1.0 - pow(VdotT, 2.0)) - VdotT * LdotT;
v_DiffuseIntensity = max(NdotL * 0.4 + 0.6, 0.0);
v_SpecularIntensity = max(pow(VdotR, 2.0) * 0.9, 0.0);
...
}
Fragment shader:
...
in lowp float v_DiffuseIntensity;
in lowp float v_SpecularIntensity;
const lowp vec3 default_color = vec3(0.1, 0.7, 0.9);
void main() {
...
lowp vec3 resultColor = (default_color * v_DiffuseIntensity)
+ v_SpecularIntensity;
outColor = vec4(resultColor, 1.0);
}
Overall, the lighting works well on different devices. But an artifact appears on the SAMSUNG tablet, as shown in the figure:
It seems that the darkest place is becoming completely black. Can anyone please suggest why this is happening? Thanks for any answer/comment!
You've got a couple of expressions that risk undefined behaviour:
sqrt(1.0 - pow(LdotT, 2.0))
sqrt(1.0 - pow(VdotT, 2.0))
The pow function is undefined if x is negative. I suspect you're getting away with this because y is 2.0 so they're probably optimised to just be x * x.
The sqrt function is undefined if x is negative. Mathematically it never should be since the magnitude of the dot product of two normalized vectors should never be more than 1, but computations always have error. I think this is causing your rendering artifacts.
I'd change those two expressions to:
sqrt(max(0.0, 1.0 - pow(max(0.0, LdotT), 2.0)))
sqrt(max(0.0, 1.0 - pow(max(0.0, VdotT), 2.0)))
The code looks a lot uglier, but it's safer and max(0.0, x) is a pretty cheap operation.
Edit: Just noticed pow(VdotR, 2.0), I'd change that too.

Refraction in OpenGL ES 2.0/3.0. Large pixels texture

Trying to implement refraction in OpenGL ES 2.0/3.0. Used the following shaders:
Vertex shader:
#version 300 es
precision lowp float;
uniform mat4 u_mvMatrix;
in vec4 a_position;
in vec3 a_normal;
...
out mediump vec2 v_refractCoord;
const mediump float eta = 0.95;
void main() {
vec4 eyePositionModel = u_mvMatrix * a_position;
// eye direction in model space
mediump vec3 eyeDirectModel = normalize(a_position.xyz - eyePositionModel.xyz);
// calculate refraction direction in model space
mediump vec3 refractDirect = refract(eyeDirectModel, a_normal, eta);
// project refraction
refractDirect = (u_mvpMatrix * vec4(refractDirect, 0.0)).xyw;
// map refraction direction to 2d coordinates
v_refractCoord = 0.5 * (refractDirect.xy / refractDirect.z) + 0.5;
...
}
Fragment shader:
...
in mediump vec2 v_refractCoord;
uniform samplerCube s_texture; // skybox
void main() {
outColor = texture(s_texture, vec3(v_refractCoord, 1.0));
}
Method for loading texture:
#JvmStatic
fun createTextureCubemap(context: Context, rowID: Int) {
val input = context.resources.openRawResource(rowID)
val bitmap = BitmapFactory.decodeStream(input)
val textureId = IntArray(1)
glGenTextures(1, textureId, 0)
glBindTexture(GL_TEXTURE_CUBE_MAP, textureId[0])
GLUtils.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, bitmap, 0)
GLUtils.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, bitmap, 0)
GLUtils.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, bitmap, 0)
GLUtils.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, bitmap, 0)
GLUtils.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, bitmap, 0)
GLUtils.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, bitmap, 0)
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
return textureId[0]
}
But the texture is obtained with large pixels like:
What could be the reason for this? Maybe this is normal for a low-poly model? It seems that the texture is too close.
Note: The fewer polygons - the less quality becomes.
Thanks in advance for any comment/answer!
image from goodfon.ru
Solution: On the #Rabbid76 advice, I changed the normal data. It turned out that in the Blender you need to set the Shading for the object as smooth (no flat) - this increases the number of normals when exporting to the format *.obj: Why OBJ export writes face normals instead of vertex normals
Also, on the #Rabbid76 advice, I changed the line:
vec3 eyeDirectModel = normalize(- eyePositionModel.xyz);
As a result, pixelation has disappeared:
In addition, pixel artifacts may also appear when calculate refraction in the vertex shader, so I transferred the calculations to the fragment shader. Here is the modified shader code:
Vertex shader:
#version 300 es
precision lowp float;
uniform mat4 u_mvpMatrix;
uniform mat4 u_mvMatrix;
in vec4 a_position;
in vec3 a_normal;
out vec3 v_normal;
out lowp float SpecularIntensity;
out vec3 v_eyeDirectModel;
float getSpecularIntensity(vec4 position, vec3 a_normal, vec3 eyeDirectModel) {
float shininess = 30.0;
vec3 lightPosition = vec3(-20.0, 0.0, 0.0);
mediump vec3 LightDirModel = normalize(lightPosition - position.xyz);
mediump vec3 halfVector = normalize(LightDirModel + eyeDirectModel);
lowp float NdotH = max(dot(a_normal, halfVector), 0.0);
return pow(NdotH, shininess);
}
void main() {
v_normal = a_normal;
vec4 eyePositionModel = u_mvMatrix * a_position;
// Eye direction in model space
vec3 eyeDirectModel = normalize(- eyePositionModel.xyz);
// specular lighting
SpecularIntensity = getSpecularIntensity(a_position, a_normal, eyeDirectModel);
v_eyeDirectModel = eyeDirectModel;
gl_Position = u_mvpMatrix * a_position;
}
Fragment shader:
#version 300 es
precision lowp float;
uniform mat4 u_mvpMatrix;
in vec3 v_normal;
in lowp float SpecularIntensity;
in vec3 v_eyeDirectModel;
out vec4 outColor;
uniform samplerCube s_texture; // skybox
const float eta = 0.65;
void main() {
// Calculate refraction direction in model space
vec3 refractDirect = refract(v_eyeDirectModel, normalize(v_normal), eta);
// Project refraction
refractDirect = (u_mvpMatrix * vec4(refractDirect, 0.0)).xyw;
// Map refraction direction to 2d coordinates
vec2 refractCoord = 0.5 * (refractDirect.xy / refractDirect.z) + 0.5;
vec4 glassColor = texture(s_texture, vec3(refractCoord, 1.0));
outColor = glassColor + SpecularIntensity;
outColor.a = 0.8; // transparent
}
First of all there is a mistake in the shader code. a_position.xyz - eyePositionModel.xyz does not make any sense, since a_position is the vertex coordinate in model space and eyePositionModel is the vertex coordinate in view space.
You have to compute the incident vector for refract in view sapce. That is the vector from the eye position to the vertex. Since the eye position in view space is (0, 0, 0), it is:
vec4 eyePositionView = u_mvMatrix * a_position;
// eye direction in model space
mediump vec3 eyeDirectView = normalize(- eyePositionView.xyz);
Furthermore, it is an issue of the normal vector attributes.
The problem is caused by the fact that the normal vectors are computed per face rather than individually for each vertex.
Note, the refraction direction (refractDirect) depends on the vertex coordinate (eyeDirectModel) and the normal vector (a_normal):
mediump vec3 refractDirect = refract(eyeDirectModel, a_normal, eta);
Since the normal vectors are different between adjacent surfaces, you can see a noticeable edge between the faces of the the mesh.
If the normal vectors are computed per vertex, then the adjacent faces share the vertex coordinates and the corresponding normal vectors. That would causes a smooth transition from face to face.

OpenGL ES 2.0 : Multiple light sources : Shader issue

UPDATE 3 (Thanks so much for your help)
I removed what was suggested. Also u_IT_MVMatrix seems wrong (what ever it is for) Things look a bit better but the floor should glow and the textured bricks should have light from the colour bricks (blue, red etc)
Vertex (fragment stayed the same) for textured Objects
uniform mat4 u_MVPMatrix; // A constant representing the combined model/view/projection matrix.
uniform mat4 u_MVMatrix; // A constant representing the combined model/view matrix.
attribute vec4 a_Position; // Per-vertex position information we will pass in.
attribute vec3 a_Normal; // Per-vertex normal information we will pass in.
attribute vec2 a_TexCoordinate; // Per-vertex texture coordinate information we will pass in.
varying vec3 v_Position; // This will be passed into the fragment shader.
varying vec3 v_Normal; // This will be passed into the fragment shader.
varying vec2 v_TexCoordinate; // This will be passed into the fragment shader.
uniform vec4 u_PointLightPositions[3]; // In eye space
uniform vec3 u_PointLightColors[3];
vec4 eyeSpacePosition;
vec3 eyeSpaceNormal;
uniform vec4 v_Color;
varying vec3 lighting;
vec3 materialColor;
vec3 getAmbientLighting();
vec3 getDirectionalLighting();
vec3 getPointLighting();
// The entry point for our vertex shader.
void main()
{
//materialColor = vec3(v_Color.xyz); // Will be modified by the texture later.
materialColor = vec3(1.0, 1.0, 1.0);
// Transform the vertex into eye space.
v_Position = vec3(u_MVMatrix * a_Position);
// Pass through the texture coordinate.
v_TexCoordinate = a_TexCoordinate;
// Transform the normal's orientation into eye space.
v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0));
// gl_Position is a special variable used to store the final position.
// Multiply the vertex by the matrix to get the final point in normalized screen coordinates.
eyeSpacePosition = u_MVMatrix * a_Position;
// The model normals need to be adjusted as per the transpose of the inverse of the modelview matrix.
eyeSpaceNormal = normalize(vec3(u_MVMatrix * vec4(a_Normal, 0.0)));
gl_Position = u_MVPMatrix * a_Position;
lighting = getAmbientLighting();
lighting += getPointLighting();
}
vec3 getAmbientLighting()
{
return materialColor * 0.2;
}
vec3 getPointLighting()
{
vec3 lightingSum = vec3(0.0);
for (int i = 0; i < 3; i++) {
vec3 toPointLight = vec3(u_PointLightPositions[i]) - vec3(eyeSpacePosition);
float distance = length(toPointLight);
//distance = distance / 5.0;
toPointLight = normalize(toPointLight);
float cosine = max(dot(eyeSpaceNormal, toPointLight), 0.0);
lightingSum += (materialColor * u_PointLightColors[i] * 20.0 * cosine)
/ distance;
}
return lightingSum;
}
**Vertex for light bricks (no texture)**
uniform mat4 u_MVPMatrix; // A constant representing the combined model/view/projection matrix.
uniform mat4 u_MVMatrix; // A constant representing the combined model/view matrix.
attribute vec4 a_Position; // Per-vertex position information we will pass in.
attribute vec3 a_Normal; // Per-vertex normal information we will pass in.
varying vec3 v_Position; // This will be passed into the fragment shader.
varying vec3 v_Normal; // This will be passed into the fragment shader.
uniform vec4 u_PointLightPositions[3]; // In eye space
uniform vec3 u_PointLightColors[3];
vec4 eyeSpacePosition;
vec3 eyeSpaceNormal;
uniform vec4 v_Color;
varying vec3 lighting;
vec3 getAmbientLighting();
vec3 getDirectionalLighting();
vec3 getPointLighting();
// The entry point for our vertex shader.
void main()
{
// Transform the vertex into eye space.
v_Position = vec3(u_MVMatrix * a_Position);
// Transform the normal's orientation into eye space.
v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0));
// gl_Position is a special variable used to store the final position.
// Multiply the vertex by the matrix to get the final point in normalized screen coordinates.
gl_Position = u_MVPMatrix * a_Position;
eyeSpacePosition = u_MVMatrix * a_Position;
// The model normals need to be adjusted as per the transpose of the inverse of the modelview matrix.
eyeSpaceNormal = normalize(vec3(u_MVMatrix * vec4(a_Normal, 0.0)));
lighting = getAmbientLighting();
lighting += getPointLighting();
}
vec3 getAmbientLighting()
{
return v_Color.xyz * 0.2;
}
vec3 getPointLighting()
{
vec3 lightingSum = vec3(0.0);
for (int i = 0; i < 3; i++) {
vec3 toPointLight = vec3(u_PointLightPositions[i]) - vec3(eyeSpacePosition);
float distance = length(toPointLight);
toPointLight = normalize(toPointLight);
float cosine = max(dot(eyeSpaceNormal, toPointLight), 0.0);
lightingSum += (v_Color.xyz * u_PointLightColors[i] * 20.0 * cosine)
/ distance;
}
return lightingSum;
}
I always struggled with using multiple light sources in a shader but I found an example in my Android OpenGL 2.0 quick start book.
Thought I would give it ago, sadly whatever I do, I seem to be the light, so when I get closer to a object it gets lighter, what I want to a make 3 different places (say street lamps) as light sources.
I define my light places and colour in my render
// new lighting
public final float[] pointLightPositions = new float[]
{0f, 1f, 0f, 1f,
100f, 1f, 0f, 1f,
50f, 1f, 0f, 1f};
public final float[] pointLightColors = new float[]
{1.00f, 0.20f, 0.20f,
0.02f, 0.25f, 0.02f,
0.02f, 0.20f, 1.00f};
On rendering
uPointLightPositionsLocation =
glGetUniformLocation(mProgramHandle, "u_PointLightPositions");
uPointLightColorsLocation =
glGetUniformLocation(mProgramHandle, "u_PointLightColors");
glUniform4fv(uPointLightPositionsLocation, 3, mRenderer.pointLightPositions, 0);
glUniform3fv(uPointLightColorsLocation, 3, mRenderer.pointLightColors, 0);
// not sure why I need this
// lighting
final float[] pointPositionsInEyeSpace = new float[12];
multiplyMV(pointPositionsInEyeSpace, 0, mVMatrix, 0, mRenderer.pointLightPositions, 0);
multiplyMV(pointPositionsInEyeSpace, 4, mVMatrix, 0, mRenderer.pointLightPositions, 4);
multiplyMV(pointPositionsInEyeSpace, 8, mVMatrix, 0, mRenderer.pointLightPositions, 8);
Matrix.multiplyMM(mRenderer.mMVPMatrix, 0, mVMatrix, 0, mRenderer.mModelMatrix, 0);
Shaders (vertex)
uniform mat4 u_MVPMatrix; // A constant representing the combined model/view/projection matrix.
uniform mat4 u_MVMatrix; // A constant representing the combined model/view matrix.
attribute vec4 a_Position; // Per-vertex position information we will pass in.
attribute vec3 a_Normal; // Per-vertex normal information we will pass in.
attribute vec2 a_TexCoordinate; // Per-vertex texture coordinate information we will pass in.
varying vec3 v_Position; // This will be passed into the fragment shader.
varying vec3 v_Normal; // This will be passed into the fragment shader.
varying vec2 v_TexCoordinate; // This will be passed into the fragment shader.
uniform vec4 u_PointLightPositions[3]; // In eye space
uniform vec3 u_PointLightColors[3];
// The entry point for our vertex shader.
void main()
{
// Transform the vertex into eye space.
v_Position = vec3(u_MVMatrix * a_Position);
// Pass through the texture coordinate.
v_TexCoordinate = a_TexCoordinate;
// Transform the normal's orientation into eye space.
v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0));
// gl_Position is a special variable used to store the final position.
// Multiply the vertex by the matrix to get the final point in normalized screen coordinates.
gl_Position = u_MVPMatrix * a_Position;
}
Fragment
precision mediump float; // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
uniform vec3 u_LightPos; // The position of the light in eye space.
uniform sampler2D u_Texture; // The input texture.
varying vec3 v_Position; // Interpolated position for this fragment.
varying vec3 v_Normal; // Interpolated normal for this fragment.
varying vec2 v_TexCoordinate; // Interpolated texture coordinate per fragment.
uniform vec4 v_Color;
uniform vec4 u_PointLightPositions[3]; // In eye space
uniform vec3 u_PointLightColors[3];
vec3 getPointLighting();
// The entry point for our fragment shader.
void main()
{
// Will be used for attenuation.
float distance = length(u_LightPos - v_Position);
// Get a lighting direction vector from the light to the vertex.
vec3 lightVector = normalize(u_LightPos - v_Position);
// Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
// pointing in the same direction then it will get max illumination.
float diffuse = max(dot(v_Normal, lightVector), 0.0);
// Add attenuation.
diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance)));
// Add ambient lighting
diffuse = diffuse + 0.7;
// Multiply the color by the diffuse illumination level and texture value to get final output color.
//gl_FragColor = (diffuse * texture2D(u_Texture, v_TexCoordinate));
gl_FragColor = diffuse * texture2D(u_Texture, v_TexCoordinate) ;
gl_FragColor *= (v_Color * vec4(getPointLighting(),v_Color.w));
}
vec3 getPointLighting()
{
vec3 lightingSum = vec3(0.0);
for (int i = 0; i < 3; i++) {
vec3 toPointLight = vec3(u_PointLightPositions[i])
- vec3(v_Position);
float distance = length(toPointLight);
toPointLight = normalize(toPointLight);
float cosine = max(dot(v_Normal, toPointLight), 0.0);
//lightingSum += vec3(0.0, 0.0, 1.0);
lightingSum += (vec3(v_Color.xyz) * u_PointLightColors[i] * 5.0 * cosine) / distance;
}
return lightingSum;
}
I would be extremely happy if someone could help :)
UPDATE 2
I have lighting, different colour but they only glow when I get really near? I am sure its something to do with u_IT_MVMatrix matrix
Fragment
uniform vec3 u_LightPos; // The position of the light in eye space.
uniform sampler2D u_Texture; // The input texture.
varying vec3 v_Position; // Interpolated position for this fragment.
varying vec3 v_Normal; // Interpolated normal for this fragment.
varying vec2 v_TexCoordinate; // Interpolated texture coordinate per fragment.
uniform vec4 v_Color;
varying vec3 lighting;
// The entry point for our fragment shader.
void main()
{
gl_FragColor = texture2D(u_Texture, v_TexCoordinate) ;
gl_FragColor *= vec4(lighting,1.0);
}
Vertex
uniform mat4 u_MVPMatrix; // A constant representing the combined model/view/projection matrix.
uniform mat4 u_MVMatrix; // A constant representing the combined model/view matrix.
attribute vec4 a_Position; // Per-vertex position information we will pass in.
attribute vec3 a_Normal; // Per-vertex normal information we will pass in.
attribute vec2 a_TexCoordinate; // Per-vertex texture coordinate information we will pass in.
varying vec3 v_Position; // This will be passed into the fragment shader.
varying vec3 v_Normal; // This will be passed into the fragment shader.
varying vec2 v_TexCoordinate; // This will be passed into the fragment shader.
uniform vec4 u_PointLightPositions[3]; // In eye space
uniform vec3 u_PointLightColors[3];
uniform vec3 u_VectorToLight; // In eye space
uniform mat4 u_IT_MVMatrix;
vec4 eyeSpacePosition;
vec3 eyeSpaceNormal;
uniform vec4 v_Color;
varying vec3 lighting;
vec3 materialColor;
vec3 getAmbientLighting();
vec3 getDirectionalLighting();
vec3 getPointLighting();
// The entry point for our vertex shader.
void main()
{
materialColor = vec3(1.0, 1.0, 1.0); // Will be modified by the texture later.
// Transform the vertex into eye space.
v_Position = vec3(u_MVMatrix * a_Position);
// Pass through the texture coordinate.
v_TexCoordinate = a_TexCoordinate;
// Transform the normal's orientation into eye space.
v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0));
// gl_Position is a special variable used to store the final position.
// Multiply the vertex by the matrix to get the final point in normalized screen coordinates.
eyeSpacePosition = u_MVMatrix * a_Position;
// The model normals need to be adjusted as per the transpose
// of the inverse of the modelview matrix.
eyeSpaceNormal = normalize(vec3(u_IT_MVMatrix * vec4(a_Normal, 0.0)));
gl_Position = u_MVPMatrix * a_Position;
lighting = getAmbientLighting();
lighting += getDirectionalLighting();
lighting += getPointLighting();
}
vec3 getAmbientLighting()
{
return materialColor * 0.2;
}
vec3 getDirectionalLighting()
{
return materialColor * max(dot(eyeSpaceNormal, u_VectorToLight), 0.0);
}
vec3 getPointLighting()
{
vec3 lightingSum = vec3(0.0);
for (int i = 0; i < 3; i++) {
vec3 toPointLight = vec3(u_PointLightPositions[i]) - vec3(eyeSpacePosition);
float distance = length(toPointLight);
toPointLight = normalize(toPointLight);
float cosine = max(dot(eyeSpaceNormal, toPointLight), 0.0);
lightingSum += (materialColor * u_PointLightColors[i] * 5.0 * cosine)
/ distance;
}
return lightingSum;
}
So I believe its something to do with my position
//multiplyMM(mModelMatrix, 0, VMatrix, 0, mModelMatrix, 0);
//invertM(tempMatrix, 0, mModelMatrix, 0);
transposeM(it_modelViewMatrix, 0, VMatrix, 0);
In your code you do have four lights, the fourth being positioned at u_LightPos.
I'd suggest you remove the diffuse variable (the fourth light) altogether and also all references to the v_Color (since you also have a texture). Then you should start seeing only the lighting of your three street lamps.
ps. I'd also move the light calculations to the vertex shader for the sake of performance.

Scaled ModelMatrix messes with Diffuse lighting

So, I have a hopefully simple question:
I have a simple cube, I'm useing Matrix.ScaleM to scale the modelview and compress the cube(There's a reason for this, trust me).
This work, the cube shrinks. However, my fragment shader no longer properly applies the diffuse light source to the top a bottom on the cube. The shade code is as follows.
precision mediump float;
uniform vec3 u_LightPos;
uniform sampler2D u_Texture;
uniform sampler2D u_Texture2;
varying vec3 v_Position;
varying vec4 v_Color;
varying vec3 v_Normal; // Interpolated normal for this fragment.
varying vec2 v_TexCoordinate; // Interpolated texture coordinate per fragment.
// The entry point for our fragment shader.
void main()
{
float distance = length(u_LightPos - v_Position);
// Get a lighting direction vector from the light to the vertex.
vec3 lightVector = normalize(u_LightPos - v_Position);
// Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
// pointing in the same direction then it will get max illumination.
float diffuse = max(dot(v_Normal, lightVector), 0.0);
mediump float emptyness = 0.0;
mediump float half_emptyness = 0.1;
// Add attenuation.
diffuse = diffuse * (1.0 / (1.0 + (0.10 * distance)));
// Add ambient lighting
diffuse = diffuse + 0.3;
vec4 textColor1 = texture2D(u_Texture, v_TexCoordinate);
vec4 textColor2 = texture2D(u_Texture2, v_TexCoordinate);
// Multiply the color by the diffuse illumination level and texture value to get final output color.
if(textColor2.w == emptyness){
diffuse = diffuse * (1.0 / (1.0 + (0.10 * distance)));
gl_FragColor = ( diffuse * textColor1 );//v_Color *
gl_FragColor.a = 1.0;
} else{
diffuse = diffuse * (1.0 / (1.0 + (0.75 * distance)));
gl_FragColor = ( diffuse * textColor1 );//v_Color *
gl_FragColor.a = 0.0;
}
}
So, any ideas?
And I know the color is a little...odd. That's for a completely different reason.
EDIT: As requested, the vertex Shader:
uniform mat4 u_MVPMatrix;
uniform mat4 u_MVMatrix;
attribute vec4 a_Position;
attribute vec4 a_Color;
attribute vec3 a_Normal;
attribute vec2 a_TexCoordinate;
varying vec3 v_Position; // This will be passed into the fragment shader.
varying vec4 v_Color; // This will be passed into the fragment shader.
varying vec3 v_Normal; // This will be passed into the fragment shader.
varying vec2 v_TexCoordinate; // This will be passed into the fragment shader.
// The entry point for our vertex shader.
void main()
{
// Transform the vertex into eye space.
v_Position = vec3(u_MVMatrix * a_Position);
// Pass through the color.
v_Color = a_Color;
// Pass through the texture coordinate.
v_TexCoordinate = a_TexCoordinate;
// Transform the normal's orientation into eye space.
v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0));
float halfer = 2.0;
// gl_Position is a special variable used to store the final position.
// Multiply the vertex by the matrix to get the final point in normalized screen coordinates.
gl_Position = u_MVPMatrix * a_Position;
}
You'll need an inverted transposed matrix like this:
Shader:
uniform mat4 u_IT_MVMatrix;
...
v_Normal = vec3(u_IT_MVMatrix * vec4(a_Normal, 0.0));
In your Java code you create the matrix from your regular MV matrix like this:
invertM(tempMatrix, 0, modelViewMatrix, 0);
transposeM(it_modelViewMatrix, 0, tempMatrix, 0);
Then you'll just need to pass this into the shader as a uniform.

Categories

Resources