GLSL multi-texturing- blending textures - opengl

I'm trying to implement multi-texturing in OpenGL. The texture used is based on the surface normal of a given vertex- The more vertical it is, the more of the second texture is visible.
Here is what I have so far.
I want to blend the edges together now rather than having that hard edge. Is it possible to blend the textures in this way? if so how do I do that?
This is my fragment shader code:
#version 150
in vec2 pass_textureCoords;
in vec3 surfaceNormal;
in vec3 toLightVector;
in vec3 toCamera;
in vec3 playerPosition;
in vec4 vertexPosition;
in float blendPosition;
in float visibility;
out vec4 out_Color;
uniform sampler2D texture0;
uniform sampler2D texture1;
uniform vec3 skyColour;
uniform vec3 light_colour;
uniform float shineDamper;
uniform float reflectivity;
void main(void){
vec3 unitNormal = normalize(surfaceNormal);
vec3 unitLightVector = normalize(toLightVector);
float nDot1 = dot(unitNormal,unitLightVector);
float brightness = max(nDot1,0.2);
vec3 diffuse = brightness * light_colour;
vec3 unitToCamera = normalize(toCamera);
vec3 lightDirection = -unitLightVector;
vec3 reflectedLightDirection = reflect(lightDirection,unitNormal);
float specular = dot(reflectedLightDirection, unitToCamera);
specular = max(specular,0.0);
float damped = pow(specular,shineDamper);
vec3 finalSpecular = damped * reflectivity * light_colour;
out_Color = (vec4(diffuse,1.0) * texture(texture0,pass_textureCoords)) + vec4(-20,-20,0.0,0.0);
out_Color = (vec4(diffuse,1.0) * texture(texture0,pass_textureCoords));
out_Color = mix(vec4(skyColour,1.0),out_Color,visibility);
if(vertexPosition.y < -6.1 || surfaceNormal.y < 0.6){
out_Color = (vec4(diffuse,1.0) * texture(texture1,pass_textureCoords)) + vec4(-20,-20,0.0,0.0);
out_Color = (vec4(diffuse,1.0) * texture(texture1,pass_textureCoords));
out_Color = mix(vec4(diffuse,1.0) * texture(texture0,pass_textureCoords),out_Color,1);
out_Color = mix(vec4(skyColour,1.0),out_Color,visibility);
}
if(playerPosition.y < -6.1){
out_Color = mix(vec4(0.0,0.3,0.5,1.0),out_Color,0.1);
}
}
EDIT:
This is the new fragment shader code for anyone interested
Updated fragment shader code:
#version 150
in vec2 pass_textureCoords;
in vec3 surfaceNormal;
in vec3 toLightVector;
in vec3 toCamera;
in vec3 playerPosition;
in vec4 vertexPosition;
in float blendPosition;
in float visibility;
out vec4 out_Color;
uniform sampler2D texture0;
uniform sampler2D texture1;
uniform vec3 skyColour;
uniform vec3 light_colour;
uniform float shineDamper;
uniform float reflectivity;
void main(void){
vec3 unitNormal = normalize(surfaceNormal);
vec3 unitLightVector = normalize(toLightVector);
float nDot1 = dot(unitNormal,unitLightVector);
float brightness = max(nDot1,0.2);
vec3 diffuse = brightness * light_colour;
vec3 unitToCamera = normalize(toCamera);
vec3 lightDirection = -unitLightVector;
vec3 reflectedLightDirection = reflect(lightDirection,unitNormal);
float specular = dot(reflectedLightDirection, unitToCamera);
specular = max(specular,0.0);
float damped = pow(specular,shineDamper);
vec3 finalSpecular = damped * reflectivity * light_colour;
out_Color.a = 1;
vec4 fog = vec4(skyColour,1.0);
vec4 diffusion = vec4(diffuse,1.0);
float a = clamp((unitNormal.y - .6)*5 + .5, 0, 0.7);
vec3 texture0_colour = (mix(fog,diffusion * texture(texture0,pass_textureCoords),visibility)).rgb;
vec3 texture1_colour = (mix(fog,diffusion * texture(texture1,pass_textureCoords),visibility)).rgb;
out_Colour.rgb = mix(texture1_colour,texture0_colour,a);
}

To mix two texture based on a value a you do:
float a = ...;
vec3 color0 = texture(texture0, pass_textureCoords).rgb;
vec3 color1 = texture(texture1, pass_textureCoords).rgb;
out_Color.rgb = mix(color0, color1, a);
Assuming that your unitNormal = (0,1,0) is the upwards direction, as it appears from the code, then the value of
float a = clamp(unitNormal.y, 0, 1);
will result in a smooth transition between the two textures. However, you probably want a sharper transition, in which case you shift and scale the unitNormal.y value to adjust where the transition starts and ends:
float a = clamp((unitNormal.y - .6)*5 + .5, 0, 1);

Related

Shadow not rendered correctly

I am trying create shadow using shadow maps. I believe that shadow map is rendered well.
It seems that sphere's shadow is not in the correct place, so how would I go about fixing that? Also why is there a black ring around the sphere and how to eliminate it?
In the shadow map vertex shader
gl_Position = u_depthMatrix * worldCoord;
In the shadow map fragment shader
fragmentdepth = gl_FragCoord.z;
vs.glsl
uniform mat4 u_Model;
uniform mat4 u_View;
uniform mat4 u_Persp;
uniform mat4 u_InvTrans;
uniform vec3 u_LightColor;
uniform vec3 u_LightDirection;
uniform vec3 u_EyePos;
uniform mat4 u_depthBiasMatrix;
in vec3 Position;
in vec3 Normal;
in vec2 Texcoord;
out vec3 v_Normal;
out vec2 v_Texcoord;
out vec3 v_Position;
out vec3 v_PositionMC;
out vec4 shadowCoord;
void main(void)
{
v_Normal = (u_InvTrans*vec4(Normal,0.0)).xyz;
vec4 world = u_Model * vec4(Position, 1.0);
vec4 cameraCoord = u_View * world;
v_Position = cameraCoord.xyz;
shadowCoord = u_depthBiasMatrix * world;
gl_Position = u_Persp * cameraCoord;
}
fs.glsl
uniform sampler2D shadowMap;
uniform vec3 u_LightColor;
uniform vec3 u_LightDirection;
uniform vec3 u_EyePos;
uniform vec3 u_Ka;
uniform vec3 u_Kd;
uniform vec3 u_Ks;
in vec3 v_Normal;
in vec2 v_Texcoord;
in vec3 v_Position; //coordinate of vertex in camera coordinate system
in vec4 shadowCoord;
void main(void)
{
vec3 v_Normal1 = normalize(v_Normal);
//Diffuse Lighting
vec3 diff = normalize(u_LightDirection - v_Position);
float diffuse = max(dot(diff , v_Normal1) , 0);
vec3 diffuseColor = diffuse * u_Kd * u_LightColor;
//Specular Lighting
vec3 v = normalize(vec3(u_EyePos - v_Position));
vec3 h = normalize(diff + v);
float sl = pow(max(dot(h, v_Normal1) , 0.0), 50);
if ( diffuse <= 0 ) sl = 0;
vec3 specularColor = sl * u_Ks * u_LightColor;
vec3 v_Color;
v_Color = u_Ka + diffuseColor + specularColor ;
//Shadow Part
vec3 shadowCoord3;
float shadowFactor = 1.0;
if(shadowCoord.w > 0 )
{
shadowCoord3 = shadowCoord.xyz / shadowCoord.w ;
if ( texture2D( shadowMap, shadowCoord3.xy ).z < shadowCoord3.z)
{
shadowFactor = 0.2;
}
}
gl_FragColor = shadowFactor * vec4(v_Color , 1);
}

Modern GLSL ( opengl 3+ ) : Implementing phong effect correctly;

I am implementing a basic phong lighting GLSL shader; I have looked up some things on the internet, and found that the phong effect was created by adding an ambient, diffuse, and specular layer on the object (see image below, from tom dalling's site); problem is I have seen a lot of examples, and none of them really suits my GLSL set-up. Can any of you give me a code example of the correct way to implement the phong effect which would fit my GLSL set-up ? :
PS : This question could be put on hold because of the fact that it may be based on user opinion : In my mind, it is not, because I would like to know the most effective, and better way of implementing it.
Here is my vertex shader :
#version 120
uniform mat4 modelView;
uniform mat4 MVP;
uniform float time;
attribute vec3 position;
attribute vec2 texCoord;
attribute vec3 normal;
varying vec3 position0;
varying vec2 texCoord0;
varying vec3 normal0;
varying mat4 modelView0;
void main()
{
//Updating varyings...
position0 = position;
texCoord0 = texCoord;
normal0 = (MVP * vec4(normal, 0.0)).xyz;
modelView0 = modelView;
//set position
gl_Position = MVP * vec4(position, 1.0);
}
and my fragment shader :
#version 120
varying vec3 position0;
varying vec2 texCoord0;
varying vec3 normal0;
varying mat4 modelView0;
uniform sampler2D diffuse;
void main()
{
vec4 surfaceColor = texture2D(diffuse, texCoord0);
gl_FragColor = (texture2D(diffuse, texCoord0))
* clamp(dot(-vec3(0.0, 0.5, 0.5), normal0), 0, 1.0);
}
try this:
void main()
{
vec4 texread = texture2D(diffuse, texCoord0);
vec3 normal = normalize(normal0);
vec3 material_kd = vec3(1.0,1.0,1.0);
vec3 material_ks = vec3(1.0,1.0,1.0);
vec3 material_ka = vec3(0.2,0.2,0.2);
vec3 material_ke = vec3(0.0,0.0,0.0);
float material_shininess = 60;
vec3 lightpos = vec3(0.0,10.0,5.0);
vec3 lightcolor = vec3(1.0,1.0,1.0);
vec3 lightdir = normalize(lightpos - worldPosition);
float shade = clamp(dot(lightdir, normal), 0.0, 1.0);
vec3 toWorldpos = normalize((worldPosition) - u_eyePos);
vec3 reflectDir = reflect( toWorldpos, normal );
vec4 specular = vec4(pow(clamp(dot(lightdir, reflectDir),0.0,1.0), material_shininess) * lightcolor * material_ks, 1.0);
vec4 shaded = texread * vec4(material_kd, 1.0) * vec4(lightcolor , 1.0) * shade;
vec4 ambient = texread * vec4(material_ka, 1.0);
vec4 emission = vec4(material_ke, 1.0);
gl_FragColor = shaded + specular + emission + ambient;
}
it may have some compilation errors though as i didnt run it...
you may need to upload your eye position as a uniform (u_eyePos), and calculate the worldposition (worldPosition) for it to work
I made my own sphong shader : here is the code :
fragment shader :
#version 150
uniform mat4 modelView;
uniform mat3 normalMatrix;
uniform vec3 cameraPosition;
uniform sampler2D materialTex;
uniform float materialShininess;
uniform vec3 materialSpecularColor;
uniform vec3 lightPosition;//light settings
uniform vec3 lightIntensities;
uniform float lightAttenuation;
uniform float lightAmbientCoeff;
in vec3 position0;
in vec2 texCoord0;
in vec3 normal0;
out vec4 fragmentColor;
void main()
{
//calculate normal in world coordinates
vec3 normal = normalize(normalMatrix * normal0);
//calculate the location of this fragment (pixel) in world coordinates
vec3 surfacePos = vec3(modelView * vec4(position0, 1));
//color of the current fragment
vec4 surfaceColor = texture(materialTex, texCoord0);
//calculate the vector from this pixels surface to the light source
vec3 surfaceToLight = normalize(lightPosition - surfacePos);
//cam distance
vec3 surfaceToCamera = normalize(cameraPosition - surfacePos);
///////////////////////////DIFUSE///////////////////////////////////////
//calculate the cosine of the angle of incidence
//float diffuseCoeff = dot(normal, surfaceToLight) / (length(surfaceToLight) * length(normal));
float diffuseCoeff = max(0.0, dot(normal, surfaceToLight));
vec3 diffuse = diffuseCoeff * surfaceColor.rgb * lightIntensities;
/////////////////////////AMBIENT////////////////////////////////////////
vec3 ambient = lightAmbientCoeff * surfaceColor.rgb * lightIntensities;
/////////////////////////SPECULAR//////////////////////////////////////
float specularCoeff = 0.0;
if(diffuseCoeff > 0.0)
specularCoeff = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), materialShininess);
vec3 specular = specularCoeff * materialSpecularColor * lightIntensities;
////////////////////////ATTENUATION///////////////////////////////////
float distanceToLight = length(lightPosition - surfacePos);
float attenuation = 1.0 / (1.0 + lightAttenuation * pow(distanceToLight, 2));
/////////////////////////////////FINAL/////////////////////////////////
vec3 linearColor = ambient + attenuation * (diffuse + specular);
//finalColor with gamma correction
vec3 gamma = vec3(1.0/2.2);
fragmentColor = vec4(pow(linearColor, gamma), surfaceColor.a);
//fragmentColor = vec4(diffuseCoeff * lightIntensities * surfaceColor.rgb, surfaceColor.a);
}

GLSL Parallax mapping issue

I wrote parallax mapping shader in GLSL but it is working wrong. In some places it shows correct image with good bump but in other positions it becomes flat. It's became most flat when I moving camera father than platform(forward)
#version 120
varying vec3 pos;
varying vec3 normal;
varying vec2 tc;
varying vec3 color;
uniform vec3 camera;
void main(void)
{
pos = (-gl_Vertex.xyz + camera);
tc = gl_MultiTexCoord0.xy;
normal = normalize(gl_Normal);
color = gl_Color.xyz;
gl_Position = ftransform();
}
#version 120
uniform sampler2D normal_map;
uniform sampler2D diffuse_map;
uniform sampler2D displacement;
uniform float mode;
varying vec2 tc;
varying vec3 pos;
void main(void)
{
vec3 lightPos = vec3( 0.0, -45.0, -40.0);
vec4 color;
if (mode > 1)
{
vec3 eyeVec = normalize(pos);
vec2 eyeProj = normalize(eyeVec.xz);
float curHeight = texture2D(displacement, tc).r - 0.5;
vec2 trTc = tc - (eyeProj) * curHeight * 0.035;
vec3 normal = normalize(texture2D(normal_map, trTc).xzy*2.0 - 1.0);
color = texture2D(diffuse_map, trTc) * dot( normalize(pos - lightPos), normal) * 1.0;
color.w = 1.0;
}
else
{
vec3 normal = normalize(texture2D(normal_map, tc).xzy*2.0 - 1.0);
color = texture2D(diffuse_map, tc) * dot( normalize(pos - lightPos), normal) * 1.0;
}
gl_FragColor = color;
}
I can't even imagine where can be mistake. I was experimenting with camera and vertex values but it is not help;

Specular Light appears on both sides

I have a very strange behaviour of specular(phong light model) light. It seems to be appering on both sides of all objects. Does anyone know what could be the issue ?
The actual calculation seems to be alright, as I can see that the light changes its position as object rotates.
#version 330
in vec4 CameraPos0;
in vec3 Pos0;
in vec4 Colour0;
in vec3 Normal0;
out vec4 FragColor;
// Ambient light parameters
uniform vec3 gAmbientLightIntensity;
// Directional light parameters
uniform vec3 gDirectionalLightIntensity;
uniform vec3 gDirectionalLightDirection;
// Specular light parameter
uniform vec3 gSpecularLightIntensity;
uniform vec3 gLightSourcePosition;
uniform vec3 gCameraPosition;
// Material constants
uniform float gKa;
uniform float gKd;
uniform float gKs;
void main()
{
// Calculate the ambient light intensity at the vertex
// Ia = Ka * ambientLightIntensity
vec4 ambientLightIntensity = gKa * vec4(gAmbientLightIntensity, 1.0);
// Setup the light direction and normalise it
vec3 lightDirection = normalize(-gDirectionalLightDirection);
//lightDirection = normalize(gDirectionalLightDirection);
// Id = kd * lightItensity * N.L
// Calculate N.L
float diffuseFactor = dot(Normal0, lightDirection);
diffuseFactor = clamp(diffuseFactor, 0.0, 1.0);
// N.L * light source colour * intensity
vec4 diffuseLightIntensity = gKd * vec4(gDirectionalLightIntensity, 1.0f) * diffuseFactor;
// Phong light
vec3 L = normalize(gLightSourcePosition - Pos0);
vec3 V = normalize(-Pos0);
vec3 R = normalize(2 * Normal0 * dot(Normal0, L) - L);
float specularFactor = pow(dot(R, V), 0.1f);
vec4 specularLightIntensity = gKs * vec4(gSpecularLightIntensity, 1.0f) * specularFactor;
specularLightIntensity = clamp(specularLightIntensity, 0.0, 1.0);
// Final vertex colour is the product of the vertex colour
// and the total light intensity at the vertex
vec4 lightedFragColor = Colour0 * (ambientLightIntensity + diffuseLightIntensity + specularLightIntensity);
FragColor = lightedFragColor;
}
Vertex Shader
#version 330
layout (location = 0) in vec3 Position;
layout (location = 1) in vec3 Normal;
layout (location = 2) in vec4 Colour;
out vec3 Pos0;
out vec4 Colour0;
out vec3 Normal0;
out vec4 CameraPos0;
uniform mat4 gModelToWorldTransform;
uniform mat4 gWorldToViewTransform;
uniform mat4 gProjectionTransform;
void main()
{
vec4 vertexPositionInModelSpace = vec4(Position, 1);
vec4 vertexInWorldSpace = gModelToWorldTransform * vertexPositionInModelSpace;
vec4 vertexInViewSpace = gWorldToViewTransform * vertexInWorldSpace;
vec4 vertexInHomogeneousClipSpace = gProjectionTransform * vertexInViewSpace;
gl_Position = vertexInHomogeneousClipSpace;
vec3 normalInWorldSpace = (gModelToWorldTransform * vec4(Normal, 0.0)).xyz;
normalInWorldSpace = normalize(normalInWorldSpace);
Normal0 = normalInWorldSpace;
CameraPos0 = vertexInViewSpace;
Pos0 = vertexInWorldSpace.xyz;
Colour0 = Colour;
}
you need to clamp the dot result from the saturation calculus because on the back side the result is negative and the pow can return a positive number instead of clamping it to zero.
float specularFactor = pow(clamp(dot(R, V),0.0,1.0), 0.1f);
Edit:
Also the V should be a vector pointing to the camera position, not to the vertex position in world space:
vec3 V = normalize(CameraPos0 - Pos0);

opengl shader directional lights specular reflection increasing with distance

the title says it all.. using opengls built in lighting system, specularlight does not increase or decrease with distance from the object, but by shader implementation does.
Vertex Shader:
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
layout (location = 2) in vec3 normal;
out vec2 texCoord0;
out vec3 normal0;
out vec3 worldPos0;
uniform mat4 transform;
uniform mat4 normalRotation;
uniform mat4 transformProjected;
void main()
{
gl_Position = transformProjected * vec4(position, 1.0);
texCoord0 = texCoord;
normal0 = normalize((normalRotation * vec4(normal, 0.0))).xyz;
worldPos0 = (transform * vec4(position, 1.0)).xyz;
}
Fragment Shader:
#version 330
in vec2 texCoord0;
in vec3 normal0;
in vec3 worldPos0;
out vec4 fragColor;
struct BaseLight
{
vec3 colorDiffuse;
vec3 colorSpecular;
float intensityDiffuse;
};
struct DirectionalLight
{
BaseLight base;
vec3 direction;
};
uniform vec3 tint;
uniform sampler2D sampler;
uniform vec3 eyePos; // camera pos
uniform vec3 ambientLight;
uniform vec3 emissiveLight;
//material
uniform float specularIntensity;
uniform float specularPower;
uniform DirectionalLight directionalLight;
vec4 calcLight(BaseLight base,vec3 direction, vec3 normal)
{
float diffuseFactor = dot(normal, -direction);
vec4 diffuseColorFinal = vec4(0,0,0,0);
vec4 specularColorFinal = vec4(0,0,0,0);
if(diffuseFactor > 0)
{
diffuseColorFinal = vec4(base.colorDiffuse,1) * diffuseFactor * base.intensityDiffuse;
vec3 directionToEye = normalize(eyePos - worldPos0);
vec3 reflectDirection = normalize(reflect(direction, normal));
float specularFactor = dot(directionToEye, reflectDirection);
specularFactor = pow(specularFactor, specularPower);
if(specularFactor > 0)
specularColorFinal = vec4(base.colorSpecular,1) * specularFactor * specularIntensity;
}
//
return diffuseColorFinal + specularColorFinal;
}
void main()
{
vec4 colorD = texture(sampler, texCoord0.xy) * vec4(tint,1);
vec3 normal = normal0;
vec4 totalLight = vec4(ambientLight,1) + vec4(emissiveLight,1);
totalLight += calcLight(directionalLight.base,-directionalLight.direction,normal);
fragColor = colorD * totalLight;
}
As you can see from the 2 images the specular light takes up a larger surface area the farther the camera gets from the plane.In my test with opengls built in lighting, this doesnt happen. is there a way to fix this? im new to lighting, maybe this is normal for directional light sources? thanks for the help!
Im also setting my eyePos uniform to my cameraPos. i dont know if that helps.
Basically you need to have distance between the fragment and the light dist . This can be a problem for directional light though because you have only the direction and distant is assumed to be infinite. Maybe switch to point light?
when youo have the 'dist' you use a formula
att = 1.0 / (Kc + Kl*dist + Kq*dist^2)
Kc - constant attenuation
Kl - linear attenuation
Kq - quadratic attenuation
simpler version (only Kq used, rest set to 1.0):
float attenuation = 1.0 / (1.0 + light.attenuation * pow(distanceToLight, 2));
then in the lighting equation you basically multiply calculated color by this att factor:
vec4 finalColor = ambient + (diffuseColorFinal + specularColorFinal)*att
http://www.ozone3d.net/tutorials/glsl_lighting_phong_p4.php#part_4
http://tomdalling.com/blog/modern-opengl/07-more-lighting-ambient-specular-attenuation-gamma/