Glsl 使灯光独立于Phong模型中的视图
我试图实现Phong着色模型,但我遇到了一些非常奇怪的事情。当我更改查看位置时,看起来灯光的行为有所不同,好像它与视图相关。例如,如果我靠近对象,我只看到环境光的效果,而如果我远离它,我开始看到漫反射的贡献 这些是我的着色器:Glsl 使灯光独立于Phong模型中的视图,glsl,webgl,lighting,phong,Glsl,Webgl,Lighting,Phong,我试图实现Phong着色模型,但我遇到了一些非常奇怪的事情。当我更改查看位置时,看起来灯光的行为有所不同,好像它与视图相关。例如,如果我靠近对象,我只看到环境光的效果,而如果我远离它,我开始看到漫反射的贡献 这些是我的着色器: //Vertex Shader attribute vec4 vPosition; attribute vec4 vNormal; varying vec3 N, L, E; uniform mat4 modelViewMatrix; uniform mat4 proj
//Vertex Shader
attribute vec4 vPosition;
attribute vec4 vNormal;
varying vec3 N, L, E;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform vec4 lightPosition;
void main()
{
vec3 pos = -(modelViewMatrix * vPosition).xyz;
vec3 light = lightPosition.xyz;
L = normalize(light - pos);
E = -pos;
N = normalize((modelViewMatrix * vNormal).xyz);
gl_Position = projectionMatrix * modelViewMatrix * vPosition;
}
我还更新了N向量的计算,因为以前的方法似乎不允许每个片段着色:
N = normalize(mat3(modelViewMatrix) * vNormal.xyz);
然而,阴影似乎随着相机的旋转而移动。这可能与光线乘以viewMatrix有关,我想是吧 光矢量的计算是错误的
L=正常化(灯-位置);
pos
是视图空间中的一个位置,light
是世界空间中的一个位置<代码>灯光是灯光在世界上的位置。因此,light-pos
毫无意义。两个矢量必须与相同的参考系相关
在将光源设置为统一的光照位置之前,通过视图矩阵变换光源的位置,以解决此问题
当然,转换也可以在着色器代码中完成:
统一mat4视图矩阵;
统一mat4模型视图矩阵;
均匀vec4光位;
void main()
{
vec3位置=(modelViewMatrix*vPosition).xyz;
vec3灯光=(viewMatrix*lightPosition).xyz;
L=正常化(灯-位置);
// ...
}
进一步注意,视图空间中的位置不必倒置。一定是这样
vec3 pos=(modelViewMatrix*vPosition).xyz;
而不是
vec3 pos=-(modelViewMatrix*vPosition).xyz;
解决你的问题总是有帮助的
问题
灯光和位置需要在同一个空间
这些可以是世界空间或视图空间,但它们必须是相同的空间
代码在视图空间中具有位置E
,但在世界空间中具有位置lightPosition
不能将法线乘以modelViewMatrix
您需要删除翻译。您还可能需要处理
与缩放问题。看
代码正在计算顶点着色器中的值,以便在传递到片段着色器时对其进行插值。这意味着它们将不再是单位向量,因此需要重新规范化它们
在计算半向量时,需要加上它们的方向
代码将L(从曲面到灯光的方向)添加到曲面的视图位置,而不是从曲面到视图的方向
在计算表面到光的方向时,该方向将是light-pos
,但代码是否定的pos
。当然,您还需要pos
为负值,曲面才能查看方向E
const gl=document.querySelector('canvas').getContext('webgl');
常数m4=twgl.m4;
常数vs=`
属性向量4位置;
属性向量4 vNormal;
不同的vec3 N,L,E;
一致mat4视图矩阵;
统一mat4模型视图矩阵;
均匀mat4投影矩阵;
均匀vec4光位;
void main()
{
vec3位置=(modelViewMatrix*vPosition).xyz;
vec3灯光=(viewMatrix*lightPosition).xyz;
L=灯-位置;
E=-pos;
N=mat3(modelViewMatrix)*vNormal.xyz;
gl_位置=投影矩阵*模型视图矩阵*位置;
}
`;
常数fs=`
高精度浮点;
均匀vec4环境积;
均匀vec4扩散产物;
均匀vec4镜面产品;
均匀的浮光度;
不同的vec3 N,L,E;
void main()
{
vec4彩色;
vec3正常=正常化(N);
vec3 surfaceToLightDir=标准化(L);
vec3 SURFACHETOVIEWDIR=标准化(E);
vec3 H=规格化(surfaceToLightDir+surfaceToViewDir);
vec4环境=环境产品;
float Kd=最大值(点(surfaceToLightDir,法线),0.0);
vec4漫反射=Kd*漫反射积;
浮子Ks=功率(最大值(点(正常,H),0.0),光泽度);
vec4镜面反射=Ks*镜面反射产品;
if(点(表面光直射,法线)<0.0){
镜面反射=vec4(0.0,0.0,0.0,1.0);
}
fColor=环境光+漫反射光+镜面反射光;
F颜色a=1.0;
gl_FragColor=fColor;
}
`;
//编译着色器、链接程序、查找位置
const programInfo=twgl.createProgramInfo(gl[vs,fs]);
常量顶点=twgl.primitives.createSphereVertices(
2,//半径
8、//周围细分
6、//向下细分
);
//调用gl.createBuffer、gl.bindBuffer、gl.bufferData
const bufferInfo=twgl.createBufferInfoFromArrays(gl{
vPosition:vertices.position,
vNormal:vertices.normal,
索引:顶点。索引,
});
函数渲染(时间){
时间*=0.001;//转换为秒
总帐启用(总帐深度测试);
总账启用(总账消隐面);
总账使用程序(programInfo.program);
//调用gl.bindBuffer、gl.enableVertexAttributeArray、gl.VertexAttributePointer
twgl.setBuffersAndAttributes(总帐、程序信息、缓冲信息);
const projectionMatrix=m4.0(
60*Math.PI/180,//视野
gl.canvas.clientWidth/gl.canvas.clientHeight,//纵横比
0.1,//znear
100,//zfar
);
常数眼=[
数学。罪(时间)*5,
3.
3+数学cos(时间)*5,
];
常量目标=[0,2,3];
const up=[0,1,0];
常量cameraMatrix=m4.注视(眼睛,目标,向上);
常量viewMatrix=m4.逆(cameraMatrix);
常数worldMatrix=m4.平移([0,2,3]);
常量modelViewMatrix=m4.乘法(viewMatrix,worldMatrix);
警察制服={
viewMatrix,
modelViewMatrix,
投影矩阵,
光照位置:[4,3,1,1],
ambientProduct:[0,0,0,1],
扩散积:[1,1,1,1],
镜面产品:[1,1,1,1],
光泽度:50,,
vec3 pos = (modelViewMatrix * vPosition).xyz;
vec3 light = (viewMatrix * lightPosition).xyz;
N = normalize(mat3(modelViewMatrix) * vNormal.xyz);