#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 vertNormal;
layout(location = 1) in vec3 eyeDir;
layout(location = 2) in vec3 lightDir[2];
layout(location = 0) out vec4 fragColor;
void main() {
vec4 ks = vec4(0.3 , 0.3 , 0.3 , 0.0);
vec4 kd = vec4(0.4 , 0.0 , 0.0 , 0.0);
vec4 kd2 = vec4(0.0 , 0.0 , 0.4 , 0.0);
vec4 ka= 0.1 * kd;
float diff = max(dot(lightDir[0] , vertNormal) , 0.0);
float diff2 = max(dot(lightDir[1] , vertNormal) , 0.0);
vec3 reflection = reflect(-lightDir[0] , vertNormal);
vec3 reflection2 = reflect(-lightDir[1] , vertNormal);
float spec = max(dot(eyeDir , reflection), 0.0);
float spec2 = max(dot(eyeDir , reflection2), 0.0);
spec = pow(spec , 14.0);
spec2 = pow(spec , 14.0);
fragColor = ka + (kd * diff) + (kd2 * diff2) + (ks * spec) + (ks * spec2);
}
Hello guys, so I was wondering, how can I make a diffuse color(float diff, diff2) as an array, so I can loop through it in future. I am a beginner, so I think the answer is very simple, I'd appreciate any help. Thanks a lot.
You can create a array like this.
float a[2] = float[2](diff, diff2);
Related
I'm trying to implement Oren-Nayar lighting in the fragment shader as shown here.
However, I'm getting some strange lighting effects on the terrain as shown below.
I am currently sending the shader the 'view direction' uniform as the camera's 'front' vector. I am not sure if this is correct, as moving the camera around changes the artifacts.
Multiplying the 'front' vector by the MVP matrix gives a better result, but the artifacts are still very noticable when viewing the terrain from some angles. It is particularly noticable in dark areas and around the edges of the screen.
What could be causing this effect?
Artifact example
How the scene should look
Vertex Shader
#version 450
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
out VS_OUT {
vec3 normal;
} vert_out;
void main() {
vert_out.normal = normal;
gl_Position = vec4(position, 1.0);
}
Tesselation Control Shader
#version 450
layout(vertices = 3) out;
in VS_OUT {
vec3 normal;
} tesc_in[];
out TESC_OUT {
vec3 normal;
} tesc_out[];
void main() {
if(gl_InvocationID == 0) {
gl_TessLevelInner[0] = 1.0;
gl_TessLevelInner[1] = 1.0;
gl_TessLevelOuter[0] = 1.0;
gl_TessLevelOuter[1] = 1.0;
gl_TessLevelOuter[2] = 1.0;
gl_TessLevelOuter[3] = 1.0;
}
tesc_out[gl_InvocationID].normal = tesc_in[gl_InvocationID].normal;
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
Tesselation Evaluation Shader
#version 450
layout(triangles, equal_spacing) in;
in TESC_OUT {
vec3 normal;
} tesc_in[];
out TESE_OUT {
vec3 normal;
float height;
vec4 shadow_position;
} tesc_out;
uniform mat4 model_view;
uniform mat4 model_view_perspective;
uniform mat3 normal_matrix;
uniform mat4 depth_matrix;
vec3 lerp(vec3 v0, vec3 v1, vec3 v2) {
return (
(vec3(gl_TessCoord.x) * v0) +
(vec3(gl_TessCoord.y) * v1) +
(vec3(gl_TessCoord.z) * v2)
);
}
vec4 lerp(vec4 v0, vec4 v1, vec4 v2) {
return (
(vec4(gl_TessCoord.x) * v0) +
(vec4(gl_TessCoord.y) * v1) +
(vec4(gl_TessCoord.z) * v2)
);
}
void main() {
gl_Position = lerp(
gl_in[0].gl_Position,
gl_in[1].gl_Position,
gl_in[2].gl_Position
);
tesc_out.normal = normal_matrix * lerp(
tesc_in[0].normal,
tesc_in[1].normal,
tesc_in[2].normal
);
tesc_out.height = gl_Position.y;
tesc_out.shadow_position = depth_matrix * gl_Position;
gl_Position = model_view_perspective * gl_Position;
}
Fragment Shader
#version 450
in TESE_OUT {
vec3 normal;
float height;
vec4 shadow_position;
} frag_in;
out vec4 colour;
uniform vec3 view_direction;
uniform vec3 light_position;
#define PI 3.141592653589793
void main() {
const vec3 ambient = vec3(0.1, 0.1, 0.1);
const float roughness = 0.8;
const vec4 water = vec4(0.0, 0.0, 0.8, 1.0);
const vec4 sand = vec4(0.93, 0.87, 0.51, 1.0);
const vec4 grass = vec4(0.0, 0.8, 0.0, 1.0);
const vec4 ground = vec4(0.49, 0.27, 0.08, 1.0);
const vec4 snow = vec4(0.9, 0.9, 0.9, 1.0);
if(frag_in.height == 0.0) {
colour = water;
} else if(frag_in.height < 0.2) {
colour = sand;
} else if(frag_in.height < 0.575) {
colour = grass;
} else if(frag_in.height < 0.8) {
colour = ground;
} else {
colour = snow;
}
vec3 normal = normalize(frag_in.normal);
vec3 view_dir = normalize(view_direction);
vec3 light_dir = normalize(light_position);
float NdotL = dot(normal, light_dir);
float NdotV = dot(normal, view_dir);
float angleVN = acos(NdotV);
float angleLN = acos(NdotL);
float alpha = max(angleVN, angleLN);
float beta = min(angleVN, angleLN);
float gamma = dot(view_dir - normal * dot(view_dir, normal), light_dir - normal * dot(light_dir, normal));
float roughnessSquared = roughness * roughness;
float roughnessSquared9 = (roughnessSquared / (roughnessSquared + 0.09));
// calculate C1, C2 and C3
float C1 = 1.0 - 0.5 * (roughnessSquared / (roughnessSquared + 0.33));
float C2 = 0.45 * roughnessSquared9;
if(gamma >= 0.0) {
C2 *= sin(alpha);
} else {
C2 *= (sin(alpha) - pow((2.0 * beta) / PI, 3.0));
}
float powValue = (4.0 * alpha * beta) / (PI * PI);
float C3 = 0.125 * roughnessSquared9 * powValue * powValue;
// now calculate both main parts of the formula
float A = gamma * C2 * tan(beta);
float B = (1.0 - abs(gamma)) * C3 * tan((alpha + beta) / 2.0);
// put it all together
float L1 = max(0.0, NdotL) * (C1 + A + B);
// also calculate interreflection
float twoBetaPi = 2.0 * beta / PI;
float L2 = 0.17 * max(0.0, NdotL) * (roughnessSquared / (roughnessSquared + 0.13)) * (1.0 - gamma * twoBetaPi * twoBetaPi);
colour = vec4(colour.xyz * (L1 + L2), 1.0);
}
First I've plugged your fragment shader into my renderer with my view/normal/light vectors and it works perfectly. So the problem has to be in the way you calculate those vectors.
Next, you say that you set view_dir to your camera's front vector. I assume that you meant "camera's front vector in the world space" which would be incorrect. Since you calculate the dot products with vectors in the camera space, the view_dir must be in the camera space too. That is vec3(0,0,1) would be an easy way to check that. If it works -- we found your problem.
However, using (0,0,1) for the view direction is not strictly correct when you do perspective projection, because the direction from the fragment to the camera then depends on the location of the fragment on the screen. The correct formula then would be view_dir = normalize(-pos) where pos is the fragment's position in camera space (that is with model-view matrix applied without the projection). Further, this quantity now depends only on the fragment location on the screen, so you can calculate it as:
view_dir = normalize(vec3(-(gl_FragCoord.xy - frame_size/2) / (frame_width/2), flen))
flen is the focal length of your camera, which you can calculate as flen = cot(fovx/2).
I know this is a long dead thread, but I've been having the same problem (for several years), and finally found the solution...
It can be partially solved by fixing the orientation of the surface normals to match the polygon winding direction, but you can also get rid of the artifacts in the shader, by changing the following two lines...
float angleVN = acos(cos_nv);
float angleLN = acos(cos_nl);
to this...
float angleVN = acos(clamp(cos_nv, -1.0, 1.0));
float angleLN = acos(clamp(cos_nl, -1.0, 1.0));
Tada!
Here is a picture of the program running:
I can't figure out why my plane is getting a bullseye coloring, I'm pretty sure I'm doing something wrong with the shaders but I'm not entirely sure what's the problem.
this is my fragment shader.
#version 430 core
in vec4 color;
in vec4 position;
uniform float fTime;
uniform vec3 lookat;
out vec4 fColor;
vec4 calculateMyNormal(vec4 mposition)
{
float dfdx = 2*(mposition.x) * 4 * cos(radians((mposition.x*mposition.x)+ (mposition.z*mposition.z)+fTime));
float dfdz = 2*(mposition.z) * 4 * cos(radians((mposition.x*mposition.x)+(mposition.z*mposition.z)+fTime));
vec3 a = vec3(1, dfdx, 0);
vec3 b = vec3(0, dfdz, 1);
vec3 normal = normalize(cross(a, b));
return vec4(normal, 1.0);
}
vec4 ADSLightModel(vec4 myNormal, vec4 myPosition)
{
const vec4 myLightPosition = vec4(1.0, 0.5, 0.0, 1.0 );
const vec4 myLightAmbient = vec4( 0.2, 0.2, 0.2, 1.0 );
const vec4 myLightDiffuse = vec4( 1.0 , 1.0 , 1.0, 1.0 );
const vec4 myLightSpecular = vec4( 1.0 , 1.0 , 1.0 , 1.0);
const vec4 myMaterialAmbient = vec4( 1.0 , 0.5, 0.0, 1.0 );
const vec4 myMaterialDiffuse = vec4( 0.5 , 0.1, 0.5, 1.0 );
const vec4 myMaterialSpecular = vec4( 0.6, 0.6, 0.6, 1.0 );
const float myMaterialShininess = 80;
vec4 norm = normalize( myNormal );
vec4 lightv = normalize( myLightPosition - myPosition );
vec4 viewv = normalize( vec4(lookat, 1.0) - myPosition );
vec4 refl = reflect( vec4(lookat, 1.0) - lightv, norm );
vec4 ambient = myMaterialAmbient*myLightAmbient;
vec4 diffuse = max(0.0, dot(lightv, norm)) * myMaterialDiffuse * myLightDiffuse;
vec4 specular = vec4( 0.0, 0.0, 0.0, 1.0 );
if( dot(lightv, viewv) > 0)
{
specular = pow(max(0.0, dot(viewv,refl)), myMaterialShininess)*myMaterialSpecular* myLightSpecular;
}
return clamp(ambient + diffuse + specular, 0.0, 1.0);
}
void main()
{
vec4 norml = calculateMyNormal(position);
fColor = ADSLightModel(norml, position);
}
the plane moves and I do that in the vertex shader, I don't know if that might be the problem.
#version 430 core
layout (location = 0) in vec4 vPosition;
uniform float fTime;
uniform mat4 mTransform;
out vec4 color;
out vec4 position;
float calculaY(float x, float z, float time)
{
return 0.5 * sin(time + (x*x + z*z) / 50.0);
}
void main()
{
vec4 vNewpos = vPosition;
vNewpos.y = calculaY(vNewpos.x, vNewpos.z, fTime);
color = vec4(0.0, 0.0, 1.0, 1.0);
position = vNewpos;
gl_Position = mTransform * vNewpos;
}
The last thing I can imagine being wrong, would be the normals, but I'm using a the code of my teacher to generate the plane and his plane had a solid color all over the plane so either he did something wrong and fixed it or as I think, the problem is in my shaders.
Your reflection vector does not really make sense:
vec4 refl = reflect( vec4(lookat, 1.0) - lightv, norm );
There are a couple of things which should make you suspicious:
refl is not normalized. The reflect operation will preserve the length of the input vector, but the input vec4(lookat, 1.0) - lightv is not normalized.
The value of vec4(lookat, 1.0) - lightv references a point, not a direction vector, since it is the difference between a point and another direction vector.
The term vec4(lookat, 1.0) - lightv does not make sense geometrically. What you want is the reflection of the light incidence vector lightv around the normal. The viewing position is totally irrelevant for determining the direction an incident light ray will be reflected to at some surface point.
The reflection vector should just be:
refl = reflect(lightv, normal);
the problem is that i pass few lights to the shader but it showing shadow only for the first one.
the lighting applied also for the lights that their shadows are not seen.
i checked the shadow maps and they being passed correctly.
the fragment shader:
#version 420 compatibility
#define MAX_LIGHTS 8
struct lightSource
{
vec4 position;
vec4 diffuse;
vec4 specular;
float constantAttenuation, linearAttenuation, quadraticAttenuation;
float spotCutoff, spotExponent, intensity;
vec3 spotDirection;
sampler2D TexShadow;
samplerCube TexShadowPoint;
};
struct material
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
float shininess;
};
uniform material frontMaterial;
uniform lightSource lights[MAX_LIGHTS];
uniform int numberOfLights;
uniform vec4 scene_ambient;
uniform mat4 inversedViewMatrix;
uniform sampler2D Tex;
uniform sampler2D TexNorm;
in vec4 position; // position of the vertex (and fragment) in world space
in vec3 varyingNormalDirection; // surface normal vector in world space
in vec2 ex_UV;
in vec4 ShadowCoords[MAX_LIGHTS];
vec2 poissonDisk[16] = vec2[](
vec2( -0.94201624, -0.39906216 ), vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ), vec2( 0.34495938, 0.29387760 ),
vec2( -0.91588581, 0.45771432 ), vec2( -0.81544232, -0.87912464 ),
vec2( -0.38277543, 0.27676845 ), vec2( 0.97484398, 0.75648379 ),
vec2( 0.44323325, -0.97511554 ), vec2( 0.53742981, -0.47373420 ),
vec2( -0.26496911, -0.41893023 ), vec2( 0.79197514, 0.19090188 ),
vec2( -0.24188840, 0.99706507 ), vec2( -0.81409955, 0.91437590 ),
vec2( 0.19984126, 0.78641367 ), vec2( 0.14383161, -0.14100790 )
);
float rand(vec2 co)
{
return fract(sin(dot(co, vec2(12.9898, 78.233)) * 43758.5453));
}
float linstep(float low, float high, float v)
{
return clamp((v-low)/(high-low), 0.0, 1.0);
}
float VSM(sampler2D depths, vec2 uv, float compare)
{
vec2 moments = texture2D(depths, uv).xy;
float p = smoothstep(compare - 0.02, compare, moments.x);
float variance = max(moments.y - moments.x*moments.x, -0.001);
float d = compare - moments.x;
float p_max;
p_max = linstep(0.6, 1.0, variance / (variance + d*d));
return clamp(max(p, p_max), 0.0, 1.0) / 2;
}
void main(void)
{
vec3 normalDirection;
//sample the normal map and covert from 0:1 range to -1:1 range
if (texture2D(TexNorm, ex_UV).rgb != vec3(0.0, 0.0, 0.0))
{
vec3 mapped_Normals = texture2D(TexNorm, ex_UV).rgb * 2.0 - 1.0;
normalDirection = normalize(mapped_Normals); //normal mapped normals
}
else
normalDirection = normalize(varyingNormalDirection);
vec4 texColor = texture2D(Tex, ex_UV);// usual processing of texture coordinates
vec3 viewDirection = normalize(vec3(inversedViewMatrix * vec4(0.0, 0.0, 0.0, 1.0) - position));
vec3 lightDirection;
float attenuation;
//initialize total lighting with ambient lighting
vec3 totalAmbientDiffuse = vec3(scene_ambient) * vec3(frontMaterial.ambient);
vec3 totalSpecular;
for (int index = 0; index < numberOfLights; index++) // for all light sources
{
float Visibility;
if (lights[index].position.w == 0.0) // directional light
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(vec3(lights[index].position));
//int num = int(rand(position.xyz) * 16);
Visibility = VSM(lights[index].TexShadow, ShadowCoords[index].xy + poissonDisk[int(rand(position.xy + vec2(position.z,-position.z)) * 16)] /2000, ShadowCoords[index].z);
}
else // point light or spotlight (or other kind of light)
{
vec3 positionToLightSource = vec3(lights[index].position - position);
float Distance = length(positionToLightSource);
lightDirection = normalize(positionToLightSource);
attenuation = 1.0 / (lights[index].constantAttenuation + lights[index].linearAttenuation * Distance + lights[index].quadraticAttenuation * Distance * Distance);
if (lights[index].spotCutoff <= 90.0) // spotlight
{
Visibility = VSM(lights[index].TexShadow, ShadowCoords[index].xy / ShadowCoords[index].w + poissonDisk[int(rand(position.xy + vec2(position.z,-position.z)) * 16)] / 700, ShadowCoords[index].z / ShadowCoords[index].w);
float clampedCosine = max(0.0, dot(-lightDirection, normalize(lights[index].spotDirection)));
if (clampedCosine < cos(radians(lights[index].spotCutoff))) // outside of spotlight cone
{
attenuation = 0.0;
}
else
{
attenuation = attenuation * pow(clampedCosine, lights[index].spotExponent);
}
}
else // point light
{
//point light shadow calculations
}
}
vec3 diffuseReflection = attenuation * vec3(lights[index].diffuse) * vec3(frontMaterial.diffuse) * max(0.0, dot(normalDirection, lightDirection));
vec3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0) // light source on the wrong side
{
specularReflection = vec3(0.0, 0.0, 0.0); // no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * vec3(lights[index].specular) * vec3(frontMaterial.specular)
* pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), frontMaterial.shininess);
}
totalAmbientDiffuse += diffuseReflection * lights[index].intensity * Visibility;
totalSpecular += specularReflection * lights[index].intensity * Visibility;
}
gl_FragColor = vec4(totalAmbientDiffuse, 1.0) * texColor + vec4(totalSpecular, 1.0);
}
I found a good example of environment mapping equirectangular. Here's the code:
VERTEX SHADER
varying vec3 Normal;
varying vec3 EyeDir;
varying float LightIntensity;
uniform vec3 LightPos;
void main(void){
gl_Position = ftransform();
Normal = normalize(gl_NormalMatrix * gl_Normal);
vec4 pos = gl_ModelViewMatrix * gl_Vertex;
EyeDir = pos.xyz;
LightIntensity = max(dot(normalize(LightPos - EyeDir), Normal), 0.0);
}
FRAGMENT SHADER
const vec3 Xunitvec = vec3 (1.0, 0.0, 0.0);
const vec3 Yunitvec = vec3 (0.0, 1.0, 0.0);
uniform vec3 BaseColor;
uniform float MixRatio;
uniform sampler2D EnvMap;
varying vec3 Normal;
varying vec3 EyeDir;
varying float LightIntensity;
void main (void){
// Compute reflection vector
vec3 reflectDir = reflect(EyeDir, Normal);
// Compute altitude and azimuth angles
vec2 index;
index.y = dot(normalize(reflectDir), Yunitvec);
reflectDir.y = 0.0;
index.x = dot(normalize(reflectDir), Xunitvec) * 0.5;
// Translate index values into proper range
if (reflectDir.z >= 0.0)
index = (index + 1.0) * 0.5;
else
{
index.t = (index.t + 1.0) * 0.5;
index.s = (-index.s) * 0.5 + 1.0;
}
// if reflectDir.z >= 0.0, s will go from 0.25 to 0.75
// if reflectDir.z < 0.0, s will go from 0.75 to 1.25, and
// that's OK, because we've set the texture to wrap.
// Do a lookup into the environment map.
vec3 envColor = vec3 (texture2D(EnvMap, index));
// Add lighting to base color and mix
vec3 base = LightIntensity * BaseColor;
envColor = mix(envColor, base, MixRatio);
gl_FragColor = vec4 (envColor, 1.0);
}
My problem is in the vertex shader.
LightIntensity = max(dot(normalize(LightPos - EyeDir), Normal), 0.0);
I'm subtracting the eye direction to the direction of light. But if I have more than one light source ... What I should do the calculation?
I use version 1.2 of GLSL.
Light is additive, so you just need to sum up the contributions of each light. If you have a fixed number of them, you can do that in a single pass through the shader—you just define a uniform for each light (position to start with, though you’ll probably want intensity/color as well) and calculate the final intensity like this:
LightIntensity = max(dot(normalize(Light1Pos - EyeDir), Normal), 0.0) + max(dot(normalize(Light2Pos - EyeDir), Normal), 0.0) + max(dot(normalize(Light3Pos - EyeDir), Normal), 0.0);
How can I get this shader to have a smooth edge on the spot light instead of a hard one? In addition, the shader has to cope with a variable value of GL_SPOT_CUTOFF. Note that not all the lights are spot lights -- GL_LIGHT0 is a point light.
varying vec3 N;
varying vec3 v;
#define MAX_LIGHTS 2
void main (void)
{
vec4 finalColour;
float spotEffect;
for (int i=0; i<MAX_LIGHTS; i++)
{
vec3 L = normalize(gl_LightSource[i].position.xyz - v);
vec3 E = normalize(-v);
vec3 R = normalize(-reflect(L,N));
spotEffect = dot(normalize(gl_LightSource[i].spotDirection),
normalize(-L));
if (spotEffect > gl_LightSource[i].spotCosCutoff) {
vec4 Iamb = gl_FrontLightProduct[i].ambient;
vec4 Idiff = gl_FrontLightProduct[i].diffuse * max(dot(N,L), 0.0);
Idiff = clamp(Idiff, 0.0, 1.0);
vec4 Ispec = gl_FrontLightProduct[i].specular
* pow(max(dot(R,E),0.0),0.3*gl_FrontMaterial.shininess);
Ispec = clamp(Ispec, 0.0, 1.0);
finalColour += Iamb + Idiff + Ispec;
}
}
gl_FragColor = gl_FrontLightModelProduct.sceneColor + finalColour;
}
The scene looks like this:
This shader from http://www.ozone3d.net/tutorials/glsl_lighting_phong_p3.php produces the soft edges to the spotlight you are after.
[Pixel_Shader]
varying vec3 normal, lightDir, eyeVec;
const float cos_outer_cone_angle = 0.8; // 36 degrees
void main (void)
{
vec4 final_color =
(gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) +
(gl_LightSource[0].ambient * gl_FrontMaterial.ambient);
vec3 L = normalize(lightDir);
vec3 D = normalize(gl_LightSource[0].spotDirection);
float cos_cur_angle = dot(-L, D);
float cos_inner_cone_angle = gl_LightSource[0].spotCosCutoff;
float cos_inner_minus_outer_angle =
cos_inner_cone_angle - cos_outer_cone_angle;
//****************************************************
// Don't need dynamic branching at all, precompute
// falloff(i will call it spot)
float spot = 0.0;
spot = clamp((cos_cur_angle - cos_outer_cone_angle) /
cos_inner_minus_outer_angle, 0.0, 1.0);
//****************************************************
vec3 N = normalize(normal);
float lambertTerm = max( dot(N,L), 0.0);
if(lambertTerm > 0.0)
{
final_color += gl_LightSource[0].diffuse *
gl_FrontMaterial.diffuse *
lambertTerm * spot;
vec3 E = normalize(eyeVec);
vec3 R = reflect(-L, N);
float specular = pow( max(dot(R, E), 0.0),
gl_FrontMaterial.shininess );
final_color += gl_LightSource[0].specular *
gl_FrontMaterial.specular *
specular * spot;
}
gl_FragColor = final_color;