我有一个只有1盏灯的公式,但我需要2盏灯 [英] I have a formula for only 1 light but I need to get 2 lights

查看:31
本文介绍了我有一个只有1盏灯的公式,但我需要2盏灯的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从头开始做一个引擎(不是出于我自己的自由意志OFC),我需要在我的对象至少有2个独立光源的地方做它。对于此公式,我使用vertex.shader和Fragment.shader。遗憾的是,此公式只能显示一个光,但如上所述,我需要使公式至少显示2个光。

这是Vertex.shader:

layout(location = 0) in vec4 vPosition;
layout(location = 1) in vec4 vNormal;
layout(location = 2) in vec2 vTexCoord;
layout(location = 3) in vec4 vTangent;
layout(location = 4) in vec4 vColor;

uniform mat4 projectionViewMatrix;
uniform mat4 modelMatrix;

out vec4 fPosition;
out vec4 fNormal;
out vec4 fColor;

void main() {
 fPosition = vPosition;
 fNormal = modelMatrix * vNormal;
 fColor = vColor;
 gl_Position = projectionViewMatrix * modelMatrix * vPosition;
}

Fragment.shader:

#version 410

in vec4 fPosition;
in vec4 fNormal;
in vec4 fColor;

uniform vec3 kAmbient;
uniform vec3 kDiffuse;
uniform vec3 kSpecular;
uniform float kSpecularPower;

uniform vec3 iDirection;
uniform vec3 iAmbient;
uniform vec3 iDiffuse;
uniform vec3 iSpecular;

uniform vec3 cameraPosition;

out vec4 pColor;

void main() {
  vec3 kNormal = normalize(fNormal.xyz);
  vec3 iNormal = normalize(iDirection);

  //Calculate ambient color
  vec3 ambientColor = (fColor.xyz + kAmbient) * iAmbient;

  //Calculate diffuse color
  float lambertTerm = dot(kNormal, -iNormal);
  lambertTerm = max(0.0f, min(1.0f, lambertTerm));
  vec3 diffuseColor = (fColor.xyz + kDiffuse) * iDiffuse * lambertTerm;

  //Calculate specular color
  vec3 surfaceToView = normalize(cameraPosition - fPosition.xyz);
  vec3 reflectionNormal = reflect(iNormal, kNormal);
  float specularTerm = dot(surfaceToView, reflectionNormal);
  specularTerm = max(0.0f, specularTerm);
  specularTerm = pow(specularTerm, kSpecularPower);
  vec3 specularColor = (fColor.xyz + kSpecular) * iSpecular * specularTerm;

  pColor = vec4(ambientColor + diffuseColor + specularColor, 1.0f);
}

我想也许我应该试着创造一个新的职位,但似乎行不通。它或者没有加载,或者是纯色。

这是我到目前为止所拥有的内容,因此您可以通过以下内容了解我要做的事情: Project

推荐答案

我了解到您的k*制服是材料属性,i*制服是灯光属性。这似乎是受到遗留的OpenGL灯光模型的启发--它一团糟,毫无意义:

  • kAmbient/iAmbient是全局场景属性,不是材质或灯光属性。
  • 当您的颜色来自顶点着色器(即fColor)时,实际上并不需要
  • kDiffuse
  • iSpecular也不需要--镜面高光的颜色由材质的镜面颜色和灯光的颜色决定,因此kSpecular*iDiffuse

将睡觉拼装成统一的区块:

struct Light {
    vec3 iDirection;
    vec3 iColor;
};

uniform Lights {
    vec3 iAmbient;
    int nlights;
    Light lights[MAX_LIGHTS];
};

uniform Material {
    //vec3 kDiffuse; // optional
    vec3 kSpecular;
    float kSpecularPower;
};

剩下的就是迭代所有灯光并累加它们的贡献:

void main() {
    vec3 kNormal = normalize(fNormal.xyz);
    vec3 surfaceToView = normalize(cameraPosition - fPosition.xyz);

    vec3 diffuse = iAmbient;
    vec3 specular = vec3(0);
    for(int i = 0; i < nlights; ++i) {
        Light light = lights[i];
        vec3 iNormal = normalize(light.iDirection);
        float lambertTerm = max(0.0f, -dot(kNormal, iNormal));
        diffuse += light.iColor * lambertTerm;
        
        vec3 reflectionNormal = reflect(iNormal, kNormal);
        float specularTerm = max(0.0f, dot(surfaceToView, reflectionNormal));
        specularTerm = pow(specularTerm, kSpecularPower);
        specular += light.iColor * specularTerm;
    }
    
    pColor = vec4(fColor.xyz*diffuse + kSpecular*specular, 1.0f);
}

这篇关于我有一个只有1盏灯的公式,但我需要2盏灯的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆