# Vulkan Phong shader problem

Light increases its intensity as it come closer the origin model.

Vertex Shader:


layout(push_constant) uniform MVPConst{
mat4 m;
mat4 v;
mat4 p;
} mvp;

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec2 inTexCoord;
layout(location = 3) in vec3 inNormal;

layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord;
layout(location = 2) out vec3 normal;
layout(location = 3) out vec3 vP;
layout(location = 4) out vec3 vD;
layout(location = 5) out vec3 wP;
layout(location = 6) out vec3 fragPos;

void main(){
vec4     wP = mvp.m * vec4(inPosition,1.0f);
mat4    mat = mvp.p * mvp.v;
gl_Position = mat * wP + vec4(.0,.5,.0,0);

normal = normalize(mat3(mvp.m) * inNormal);
fragTexCoord = inTexCoord;
fragColor = inColor;
vP = vec3(mvp.v[3][0], mvp.v[3][1], mvp.v[3][2]);
vD = normalize(vP - wP.xyz);
}


Frag Shader:

#version 450

#define PI 3.14159265359

layout(binding = 0) uniform UBO{
vec4  vP;
vec4  vD;
vec4  lP;
float time;
uvec2 res;
float sharp;
mat4  vM;
mat4  invvM;
} ubo;

layout(binding = 1) uniform sampler2DArray texSampler;

layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTexCoord;
layout(location = 2) in vec3 normal;
layout(location = 3) in vec3 vP;
layout(location = 4) in vec3 vD;//Maybe problem
layout(location = 5) in vec3 wP;
layout(location = 6) in vec3 fragPos;

layout(location = 0) out vec4 outColor;

uvec2 res     = ubo.res;
float time    = ubo.time;

vec3 specular(){
vec3 diffuseLight = vec3(1.);
vec3 specularLight = vec3(.0);
vec3 surfaceNormal = normalize(normal);

vec3 cameraPosWorld = ubo.invvM[3].xyz;
vec3 viewDirection = normalize(cameraPosWorld - wP);

vec3 directionToLight = ubo.lP.xyz - wP.xyz;
float attenuation = 1.0 / dot(directionToLight, directionToLight); // distance squared
directionToLight = normalize(directionToLight);

float cosAngIncidence = max(dot(surfaceNormal, directionToLight), 0);
vec3 intensity = vec3(1.,0.,0.) * attenuation * 1.5;

diffuseLight += intensity * cosAngIncidence;

vec3 halfAngle = normalize(directionToLight + viewDirection);
float blinnTerm = dot(surfaceNormal, halfAngle);
blinnTerm = clamp(blinnTerm, 0, 1);
blinnTerm = pow(blinnTerm, 512.0); // higher values -> sharper highlight
specularLight += intensity * blinnTerm;

vec3 color = texture(texSampler,vec3(fragTexCoord,2)).rgb;
vec3 ambient = .2 * color;
return ambient * diffuseLight;
}

void main(){
vec2 vpuv = fragPos.xy / res;
vpuv.y    = 1. - vpuv.y;

outColor.rgb = specular();
}


cpp code:

if(_camera.ang.x > 360.f)      _camera.ang.x = 0.f;
else if(_camera.ang.x < 0.f)   _camera.ang.x = 360.f;
if(_camera.ang.y > 89.f)     _camera.ang.y = 89.f;
else if(_camera.ang.y < -89.f) _camera.ang.y = -89.f;
if(_camera.ang.z > 360.f)     _camera.ang.z =  0.f;
else if(_camera.ang.z <  0.f)  _camera.ang.z = 360.f;

_camera.dir.x = cos(glm::radians(_camera.ang.x)) * cos(glm::radians(_camera.ang.y));
_camera.dir.y = sin(glm::radians(_camera.ang.x)) * cos(glm::radians(_camera.ang.y));
_camera.dir.z = sin(glm::radians(_camera.ang.y));
_camera.dir   = glm::normalize(_camera.dir);

objAng.second = vec3(0.f,1.f,1.f);
glm::mat4 m      = glm::rotate(glm::mat4(1.0f), radians(sharpness), objAng.second);
m      = glm::translate(m,obju->pos);
glm::mat4 v      = glm::lookAt(_camera.pos, _camera.pos + _camera.dir, glm::vec3(0.f,0.f,1.f));
glm::mat4 p       = glm::perspective(glm::radians(60.f), _swapChnExtent.width / (float) _swapChnExtent.height, 0.1f, 1000.0f);
p[1][1] *= -1;

_camera.view = v;

_camera.invview[0][0] = _camera.view[0][0];
_camera.invview[0][1] = _camera.view[1][0];
_camera.invview[0][2] = _camera.view[2][0];
_camera.invview[1][0] = _camera.view[0][1];
_camera.invview[1][1] = _camera.view[1][1];
_camera.invview[1][2] = _camera.view[2][1];
_camera.invview[2][0] = _camera.view[0][2];
_camera.invview[2][1] = _camera.view[1][2];
_camera.invview[2][2] = _camera.view[2][2];
_camera.invview[3][0] = _camera.pos.x;
_camera.invview[3][1] = _camera.pos.y;
_camera.invview[3][2] = _camera.pos.z;
MVP pconst;
pconst.m = m;
pconst.v = v;
pconst.p = p;

vkCmdPushConstants(info.cmdBuf,_graphxPlineLayt,VK_SHADER_STAGE_VERTEX_BIT,0,sizeof(MVP),&pconst);
vkCmdBindDescriptorSets(info.cmdBuf,VK_PIPELINE_BIND_POINT_GRAPHICS,_graphxPlineLayt,0,1,&_descrSets[_crntFram],0,nullptr);

vkCmdDrawIndexed(info.cmdBuf,static_cast<uint32_t>(obju->inds.size()),1,0,0,0);


cpp code2:

UBO ubo{};
ubo.vP    = glm::vec4(_camera.pos,1.f);
ubo.vD    = glm::vec4(_camera.dir,1.f);
ubo.lP    = glm::vec4(lightPos,1.f);
ubo.time  = time;
ubo.sharp = sharpness;
ubo.vM    = _camera.view;
ubo.invvM = _camera.invview;

if(_framBufRsz || _isInitialized){
ubo.res = vec2(_swapChnExtent.width,_swapChnExtent.height);
}

void* data;
vkMapMemory(_device,_unifBufsMems[crntImg],0,sizeof(ubo),0,&data);
memcpy(data,&ubo,sizeof(ubo));
vkUnmapMemory(_device,_unifBufsMems[crntImg]);


Position of light equal to camera position

• I cleaned and reorganized code, and now its working! Commented Nov 6, 2023 at 21:50

## 1 Answer

Final fragment shader

#version 450

#define PI 3.14159265359

layout(binding = 0) uniform UBO{
vec4  vP;
vec4  vD;
vec4  lP;
float time;
uvec2 res;
float sharp;
mat4  vM;
mat4  invvM;
} ubo;

layout(binding = 1) uniform sampler2DArray texSampler;

layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTexCoord;
layout(location = 2) in vec3 fragNormal;
layout(location = 3) in vec3 fragPosWorld;

layout(location = 0) out vec4 outColor;

uvec2 res  = ubo.res;
float time = ubo.time;

vec3 specular(){
vec3  diffuseLight = vec3(1.);
vec3 specularLight = vec3(.0);
vec3 surfaceNormal = normalize(fragNormal);

vec3 cameraPosWorld = ubo.invvM[3].xyz;
vec3  viewDirection = normalize(cameraPosWorld - fragPosWorld);

vec3 directionToLight = ubo.lP.xyz - fragPosWorld.xyz;
float     attenuation = 1.0 / dot(directionToLight, directionToLight);
directionToLight = normalize(directionToLight);

float cosAngIncidence = max(dot(surfaceNormal, directionToLight), 0);
vec3        intensity = vec3(.992,.647,.059) * attenuation * 1.5;
diffuseLight += intensity * cosAngIncidence;

vec3  halfAngle  = normalize(directionToLight + viewDirection);
float blinnTerm  = dot(surfaceNormal, halfAngle);
blinnTerm  = clamp(blinnTerm, 0, 1);
blinnTerm  = pow(blinnTerm,16.0);
specularLight += intensity * blinnTerm;

vec3   color = texture(texSampler,vec3(fragTexCoord,2)).rgb;
vec3 ambient = .2 * color;

return ambient * diffuseLight + specularLight * color;
}

void main(){
vec2 vpuv = gl_FragCoord.xy / res;
vpuv.y    = 1. - vpuv.y;

outColor.rgb = specular();
}
$$$$
`
• This answer would be more useful to future readers struggling with similar problems if you explained what you changed and how it fixed the problem. Commented Nov 6, 2023 at 21:56