我正在尝试在GLSL中实现phong着色,但我对镜面反射组件有一些问题。
绿灯是镜面反射分量。光(点光源)在平面上方以圆形传播。镜面反射高光总是朝向Y轴向内指向,光线围绕Y轴旋转,并朝向漫反射扇出,如图中所示。相机的定位似乎没有影响,我不知道我哪里出错了。
顶点着色器代码:
#version 330 core
/*
* Phong Shading with with Point Light (Quadratic Attenutation)
*/
//Input vertex data
layout(location = 0) in vec3 vertexPosition_modelSpace;
layout(location = 1) in vec2 vertexUVs;
layout(location = 2) in vec3 vertexNormal_modelSpace;
//Output Data; will be interpolated for each fragment
out vec2 uvCoords;
out vec3 vertexPosition_cameraSpace;
out vec3 vertexNormal_cameraSpace;
//Uniforms
uniform mat4 mvMatrix;
uniform mat4 mvpMatrix;
uniform mat3 normalTransformMatrix;
void main()
{
vec3 normal = normalize(vertexNormal_modelSpace);
//Set vertices in clip space
gl_Position = mvpMatrix * vec4(vertexPosition_modelSpace, 1);
//Set output for UVs
uvCoords = vertexUVs;
//Convert vertex and normal into eye space
vertexPosition_cameraSpace = mat3(mvMatrix) * vertexPosition_modelSpace;
vertexNormal_cameraSpace = normalize(normalTransformMatrix * normal);
}
片段着色器代码:
#version 330 core
in vec2 uvCoords;
in vec3 vertexPosition_cameraSpace;
in vec3 vertexNormal_cameraSpace;
//out
out vec4 fragColor;
//uniforms
uniform sampler2D diffuseTex;
uniform vec3 lightPosition_cameraSpace;
void main()
{
const float materialAmbient = 0.025; //a touch of ambient
const float materialDiffuse = 0.65;
const float materialSpec = 0.35;
const float lightPower = 2.0;
const float specExponent = 2;
//--------------Set Colors and determine vectors needed for shading-----------------
//reflection colors- NOTE- diffuse and ambient reflections will use the texture color
const vec3 colorSpec = vec3(0,1,0); //Green spec color
vec3 diffuseColor = texture2D(diffuseTex, uvCoords).rgb; //Get color from the texture at fragment
const vec3 lightColor = vec3(1,1,1); //White light
//Re-normalize normal vectors : after interpolation they make not be unit length any longer
vec3 normVertexNormal_cameraSpace = normalize(vertexNormal_cameraSpace);
//Set camera vec
vec3 viewVec_cameraSpace = normalize(-vertexPosition_cameraSpace); //Since its view space, camera at origin
//Set light vec
vec3 lightVec_cameraSpace = normalize(lightPosition_cameraSpace - vertexPosition_cameraSpace);
//Set reflect vect
vec3 reflectVec_cameraSpace = normalize(reflect(-lightVec_cameraSpace, normVertexNormal_cameraSpace)); //reflect function requires incident vec; from light to vertex
//----------------Find intensity of each component---------------------
//Determine Light Intensity
float distance = abs(length(lightPosition_cameraSpace - vertexPosition_cameraSpace));
float lightAttenuation = 1.0/( (distance > 0) ? (distance * distance) : 1 ); //Quadratic
vec3 lightIntensity = lightPower * lightAttenuation * lightColor;
//Determine Ambient Component
vec3 ambientComp = materialAmbient * diffuseColor * lightIntensity;
//Determine Diffuse Component
float lightDotNormal = max( dot(lightVec_cameraSpace, normVertexNormal_cameraSpace), 0.0 );
vec3 diffuseComp = materialDiffuse * diffuseColor * lightDotNormal * lightIntensity;
vec3 specComp = vec3(0,0,0);
//Determine Spec Component
if(lightDotNormal > 0.0)
{
float reflectDotView = max( dot(reflectVec_cameraSpace, viewVec_cameraSpace), 0.0 );
specComp = materialSpec * colorSpec * pow(reflectDotView, specExponent) * lightIntensity;
}
//Add Ambient + Diffuse + Spec
vec3 phongFragRGB = ambientComp +
diffuseComp +
specComp;
//----------------------Putting it together-----------------------
//Out Frag color
fragColor = vec4( phongFragRGB, 1);
}
注意顶点着色器中看到的normalTransformMatrix是模型视图矩阵的反转置。
我正在相机空间中设置从顶点位置到光线,相机和反射矢量的矢量。对于漫反射计算,我采用光矢量和法向矢量的点积,对于镜面反射分量,我采用反射矢量和视图矢量的点积。也许我对算法有一些根本的误解?
我首先想到的问题可能是我没有规范化插值后插入片段着色器的法线,但是添加一行来规范化并不会影响图像。我不确定在哪里看。
我知道网站上有很多phong着色问题,但每个人似乎都有一个有点不同的问题。如果有人能看到我出错的地方,请告诉我。任何帮助表示赞赏。
编辑:好的,它现在正在工作!正如jozxyqk在下面建议的那样,我需要对我的顶点位置进行mat4 * vec4操作或丢失翻译信息。当我第一次做出改变时,我得到了奇怪的结果,直到我意识到我在我的OpenGL代码中为lightPosition_cameraSpace犯了同样的错误,然后才将它传递给着色器(错误是我将视图矩阵转换为mat3用于计算而不是将光位置矢量设置为vec4)。编辑完这些线后,着色器似乎正常工作!谢谢你的帮助,jozxqk!答案 0 :(得分:2)
我可以看到两个看起来不正确的部分。
<击> 2。 distance使用相对于相机的光位置而不是顶点。请改用lightVec_cameraSpace。(编辑:错过了重复的计算)