Glsl 使灯光独立于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

我试图实现Phong着色模型,但我遇到了一些非常奇怪的事情。当我更改查看位置时,看起来灯光的行为有所不同,好像它与视图相关。例如,如果我靠近对象,我只看到环境光的效果,而如果我远离它,我开始看到漫反射的贡献

这些是我的着色器:

//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);