我有一个只有1盏灯的公式,但我需要2盏灯 [英] I have a formula for only 1 light but I need to get 2 lights
本文介绍了我有一个只有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屋!
查看全文