当对象被翻译时,静态光继续移动

时间:2014-09-22 15:57:14

标签: opengl glsl webgl

为什么我的相机移动灯光?在我的绘制场景功能中,我设置了我的光源位置,然后我调用我的矩阵,翻译"相机",然后是球体,然后是两个立方体。当我将相机与第一个立方体一起移动时,光源随之移动......

 function drawScene() {
    gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);

    //currentProgram = perFragmentProgram;
    currentProgram = perVertexProgram;
    gl.useProgram(currentProgram);

    gl.uniform3f(
        currentProgram.ambientColorUniform,
        parseFloat(document.getElementById("ambientR").value),
        parseFloat(document.getElementById("ambientG").value),
        parseFloat(document.getElementById("ambientB").value)
    );

    gl.uniform3f(
         currentProgram.pointLightingLocationUniform,
         parseFloat(document.getElementById("lightPositionX").value),
         parseFloat(document.getElementById("lightPositionY").value),
         parseFloat(document.getElementById("lightPositionZ").value)
    );

    gl.uniform3f(
        currentProgram.pointLightingColorUniform,
        parseFloat(document.getElementById("pointR").value),
        parseFloat(document.getElementById("pointG").value),
        parseFloat(document.getElementById("pointB").value)
    );

    mat4.identity(mvMatrix);

    //Camera
    mat4.translate(mvMatrix, [-xPos, -yPos, -10]);
    mat4.rotate(mvMatrix, degToRad(180), [0, 1, 0]);

    //Sphere
    mvPushMatrix();
    mat4.rotate(mvMatrix, degToRad(moonAngle), [0, 1, 0]);
    mat4.translate(mvMatrix, [5, 0, 0]);

    gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexPositionBuffer);
    gl.vertexAttribPointer(currentProgram.vertexPositionAttribute, moonVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexNormalBuffer);
    gl.vertexAttribPointer(currentProgram.vertexNormalAttribute, moonVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, moonVertexIndexBuffer);
    setMatrixUniforms();
    gl.drawElements(gl.TRIANGLES, moonVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
    mvPopMatrix();

    //Cube 1
    object.render(xPos, yPos);

    //Cube 2
    object2.render(0, 5);
}

我的着色器看起来像这样。

<script id="per-vertex-lighting-fs" type="x-shader/x-fragment">
precision mediump float;

varying vec3 vLightWeighting;

void main(void) {
    vec4 fragmentColor;
    fragmentColor = vec4(1.0, 1.0, 1.0, 1.0);
    gl_FragColor = vec4(fragmentColor.rgb * vLightWeighting, fragmentColor.a);
}
</script>

<script id="per-vertex-lighting-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat3 uNMatrix;

uniform vec3 uAmbientColor;

uniform vec3 uPointLightingLocation;
uniform vec3 uPointLightingColor;

uniform bool uUseLighting;

varying vec2 vTextureCoord;
varying vec3 vLightWeighting;

void main(void) {
    vec4 mvPosition = uMVMatrix * vec4(aVertexPosition, 1.0);
    gl_Position = uPMatrix * mvPosition;


    vec3 lightDirection = normalize(uPointLightingLocation - mvPosition.xyz);

    vec3 transformedNormal = uNMatrix * aVertexNormal;
    float directionalLightWeighting = max(dot(transformedNormal, lightDirection), 0.0);

    vLightWeighting = uAmbientColor + uPointLightingColor * directionalLightWeighting;

}
</script>

我该怎么做才能阻止灯光被移动,使其静止

1 个答案:

答案 0 :(得分:1)

uPointLightingLocation必须位于眼睛空间中,与您将其与点积进行比较的transformedNormal匹配。

通过视图 / 相机矩阵乘以lightPosition(假设它在世界空间中)。在着色器外部执行此操作会更便宜,因为在渲染过程中值不会发生变化。

视图矩阵已经存在于代码中间的 model-view 构造中。 //Camera块是视图//Sphere块在模型转换中相乘。要仅提取视图,请在mvMatrixCamera转换块之间复制Sphere(或者只转换灯光然后转换灯光)。

//untested, but something along these lines
var worldSpaceLight = vec4.fromValues( //not sure which lib your using
     parseFloat(document.getElementById("lightPositionX").value),
     parseFloat(document.getElementById("lightPositionY").value),
     parseFloat(document.getElementById("lightPositionZ").value),
     1.0
);
...
//Camera
...
var eyeSpaceLight = vec4.create();
vec4.transformMat4(eyeSpaceLight, worldSpaceLight, mvMatrix);
gl.uniform3f(currentProgram.pointLightingLocationUniform, eyeSpaceLight);
//Sphere
...