一点点个人思路总结
写在前面的话,到现在位置,我们做的一切事情都是和pipeline有关,而且在写的过程中也深有体会,vertexShader和FragmentShader非常重要,其中有地方修改会导致在renderloop中也需要修改很多大小。
另外这这里我想再重复谈谈我的对于整体流程的想法。
一个图形渲染器,有一个大体的思路就是,现在有一个放了很多物体的场景,使用一堆数组表示的,现在我需要把这个3D场景变成2D画面该如何做到。
在OpenGL中,分为cpu和gpu。
一条线是:数组从cpu传到gpu中保存在VBO中,通过他的bossVAO来将数据分类分组,这个VAO有的时候还需要EBO这个小弟来帮忙分辨一下。在这个VAO管理VBO的过程中也会将数据传给vertexShader。
另外一条线:vertexShader根据传进来的数据对顶点进行处理(插值等)然后给fragmentShader。在fragment中我们会有更多操作,纹理、光照等,实现对每一个像素点的颜色确定。
视角回到render loop 中,在每一帧的渲染过程中,我们需要不断重复以下这些事情:
确定每个物体的MVP,确定纹理,确定光照,然后绘制。
okok现在开始今天具体要实现的事情:多光源
换句话说,之前写了那么多不同光的类,我现在要把他们合起来,因为他们有很多共同点。
定向光
重新写shader,然后这里再次提醒一下,一个像素点的颜色由光照中的diffuse(光的漫反射量*材质中的漫反射贴图) specular(镜面反射量*镜面反射贴图)。
#version 330 core
struct Material{
vec3 ambient;
sampler2D diffuse;
sampler2D specular;
sampler2D emission;
float shininess;
};
struct LightDirectional{
vec3 pos;
vec3 color;
vec3 dirToLight;
};
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoord;
uniform LightDirectional lightD;
uniform Material material;
//uniform sampler2D ourTexture;
//uniform sampler2D ourFace;
uniform vec3 objColor;
uniform vec3 ambientColor;
uniform vec3 cameraPos;
uniform float time;
out vec4 FragColor;
vec3 CalcLightDirectional(LightDirectional light,vec3 uNormal,vec3 dirToCamera)
{
//diffuse
float diffInensity = max(dot(light.dirToLight,uNormal),0);
vec3 diffColor = diffInensity * light.color * texture(material.diffuse,TexCoord).rgb;
//specular
vec3 ref = normalize( reflect(-light.dirToLight,uNormal));
float specIntensity = pow(max(dot(ref,dirToCamera),0),material.shininess);
vec3 specColor = specIntensity *light.color * texture(material.specular,TexCoord).rgb;
vec3 result = diffColor+specColor;
return result;
};
void main()
{
vec3 finalResult=vec3(0,0,0);
vec3 uNormal = normalize(Normal);
vec3 dirToCamera = normalize(cameraPos - FragPos);
finalResult += CalcLightDirectional(lightD,uNormal,dirToCamera);
FragColor = vec4(finalResult,1.0f);
}
点光源
和前面一样
vec3 CalcLightPont(LightPoint light,vec3 uNormal,vec3 dirToCamera)
{
//attenation
float dist = length(light.pos - FragPos);
float attenuation = 1.0/(light.constant+light.linear*dist+light.quadratic*dist*dist);
//diffuse
float diffInensity = max(dot(normalize(light.pos-FragPos),uNormal),0)*attenuation;
vec3 diffColor = diffInensity * light.color * texture(material.diffuse,TexCoord).rgb;
//specualr
vec3 ref = normalize( reflect(FragPos- light.pos,uNormal));
float specIntensity = pow(max(dot(ref,dirToCamera),0),material.shininess)*attenuation;
vec3 specColor = specIntensity *light.color * texture(material.specular,TexCoord).rgb;
vec3 result = diffColor + specColor;
return result;
};
聚光
不过这里加上了衰减,那就加吧。
vec3 CalcLightSpot(LightSpot light,vec3 uNormal,vec3 dirToCamera)
{
//attenation
float dist = length(light.pos - FragPos);
float attenuation = 1.0/(light.constant+light.linear*dist+light.quadratic*dist*dist);
//平滑阴影
float cosTheta = dot( normalize(FragPos-lightS.pos), -1*light.dirToLight);
float SpotRatio ;
if(cosTheta>light.cosInnerPhy){
//inside
SpotRatio = 1.0f;
}else if(cosTheta >light.cosOutPhy){
//middle
SpotRatio = (cosTheta-light.cosOutPhy)/(light.cosInnerPhy-light.cosOutPhy);
}else{
//outside
SpotRatio = 0;
}
//diffuse
float diffInensity = max(dot(normalize(light.pos-FragPos),uNormal),0)*attenuation*SpotRatio;
vec3 diffColor = diffInensity * light.color * texture(material.diffuse,TexCoord).rgb;
//specualr
vec3 ref = normalize( reflect(FragPos- light.pos,uNormal));
float specIntensity = pow(max(dot(ref,dirToCamera),0),material.shininess)*attenuation*SpotRatio;
vec3 specColor = specIntensity *light.color * texture(material.specular,TexCoord).rgb;
vec3 result = (diffColor+specColor);
return result;
};