OpenGL ES 2.0 : Multiple light sources : Shader issue - android

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.

Related

Directional lighting is not constant in OpenGL ES 2.0/3.0

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);
// [...]
}

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.

GLSL 2.0 Shader giving different light in different device

I am trying to write a shader for a opengles 2.0 view in Android.
My shader is :
Vertex shader:
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.
// 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 = normalize(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 Shader:
precision highp float; // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
uniform vec3 u_LightPos1; // The position of the light in eye space.
uniform vec3 u_LightDir1; // The position of the light in eye space.
float l_spotCutOff=45.0;
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.
float cutoff = 0.1;
// The entry point for our fragment shader.
void main()
{
// Get a lighting direction vector from the light to the vertex.
vec3 lightVector1 = normalize(u_LightPos1 - v_Position);
// Will be used for attenuation.
float distance1 = length(u_LightPos1 - v_Position);
float diffuse=0.0;
// 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 diffuse1 = max(dot(v_Normal, lightVector1), 0.1);
// Add attenuation.
diffuse1 = diffuse1 * (1.0 / (1.0+(0.25*distance1)));
// Add ambient lighting
diffuse = diffuse1+0.2;
// Multiply the color by the diffuse illumination level and texture value to get final output color.
vec4 color = (texture2D(u_Texture, v_TexCoordinate));
color.rgb *= (diffuse);
if( color.a < cutoff)
discard;
gl_FragColor = color;
}
Now the shaders are working perfectly but its behaving differently in different device:
Device 1: (moto x play)
1
Device 2: (Samsung S7)
2
Can anyone help?
The issue can be there in texture format/type which you have used. All devices doesn't support all texture formats.
for eg : if your output color can have negative values and the texture format of device doesn't support them, it will get clamped to 0 and might give different results.
Better to check capabilities of both devices using
GLES20.glGetString(GLES20.GL_EXTENSIONS));

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.

OpenGLES 2.0 Phong shader strange result, makes my object transparent when texture is enabled!

I've been stuck for several days now, trying to make my shader working properly.
The problem is that when I'm not attaching a texture on my object, I multiply the ambient by the light color and I get a dark object when no light, and illuminated properly when a light source is activated.
The problem is that when I attach a texture and multiply it by ambient and light color I get a transparent object that shows up only when a light source is activated, and you can even see through the object while it is illuminated!
I've been trying several codes snippets from the internet but I always get the same result. What I'm doing wrong here? I'm desperate...
The application is developed on Android.
Here is my Vertex Shader:
uniform mat4 uMVPMatrix;
uniform mat4 normalMatrix;
// eye pos
uniform vec3 eyePos;
// position and normal of the vertices
attribute vec4 aPosition;
attribute vec3 aNormal;
// texture variables
uniform float hasTexture;
varying float tex;
attribute vec2 textureCoord;
varying vec2 tCoord;
// lighting
uniform vec4 lightPos;
uniform vec4 lightColor;
// material
uniform vec4 matAmbient;
uniform vec4 matDiffuse;
uniform vec4 matSpecular;
uniform float matShininess;
// normals to pass on
varying vec3 vNormal;
varying vec3 EyespaceNormal;
varying vec3 lightDir, eyeVec;
void main() {
// pass on texture variables
tex = hasTexture;
tCoord = textureCoord;
// normal
EyespaceNormal = vec3(normalMatrix * vec4(aNormal, 1.0));
// the vertex position
vec4 position = uMVPMatrix * aPosition;
// light dir
lightDir = lightPos.xyz - position.xyz;
eyeVec = -position.xyz;
gl_Position = uMVPMatrix * aPosition;
}
And here is my Fragment shader:
precision mediump float;
// texture variables
uniform sampler2D texture1; // color texture
varying float tex;
varying vec2 tCoord;
varying vec3 vNormal;
varying vec3 EyespaceNormal;
// light
uniform vec4 lightPos;
uniform vec4 lightColor;
// material
uniform vec4 matAmbient;
uniform vec4 matDiffuse;
uniform vec4 matSpecular;
uniform float matShininess;
// eye pos
uniform vec3 eyePos;
// from vertex s
varying vec3 lightDir, eyeVec;
void main() {
vec4 b = lightColor;
vec4 c = matAmbient;
vec4 d = matDiffuse;
vec4 e = matSpecular;
vec3 g = eyePos;
float f = matShininess;
vec3 N = normalize(EyespaceNormal);
vec3 E = normalize(eyeVec);
vec3 L = normalize(lightDir);
// Reflect the vector. Use this or reflect(incidentV, N);
vec3 reflectV = reflect(-L, N);
// Get lighting terms
vec4 ambientTerm;
if (tex >= 1.0) {
ambientTerm = texture2D(texture1, tCoord);
}
else
ambientTerm = matAmbient * lightColor;
vec4 diffuseTerm = matDiffuse * max(dot(N, L), 0.0);
vec4 specularTerm = matSpecular * pow(max(dot(reflectV, E), 0.0), matShininess);
gl_FragColor = ambientTerm * diffuseTerm + specularTerm;
}
Thanks in advance.
OK I found it, thanks to JPD002, I was revising the shader again, and I found out that it has to be
vec4 diffuseTerm = matDiffuse * max(dot(N, L), 0.0);
vec4 specularTerm = matSpecular * pow(max(dot(reflectV, E), 1.0), matShininess);
Thanks JDP002, it is always good to have 4 eyes on code rather than 2 =D

Categories

Resources