c# - 在 GLSL 中复制 GL 中间模式光照模型
问题描述
所以,我现在处于头晕目眩的阶段......
我正在尝试做的是在 GLSL 中重新创建现有的中间模式照明引擎。
归根结底,中间模式非常简单,只有环境光和单一定向光,如下所示:
GL.Light(LightName.Light0, LightParameter.Position, new[] { (float)Lighting.OptionLightPosition.X, (float)Lighting.OptionLightPosition.Y, (float)-Lighting.OptionLightPosition.Z, 0.0f });
GL.Light(LightName.Light0, LightParameter.Ambient,new Color4(OptionAmbientColor.R,OptionAmbientColor.G,OptionAmbientColor.B,255));
GL.Light(LightName.Light0, LightParameter.Diffuse, new Color4(OptionDiffuseColor.R, OptionDiffuseColor.G, OptionDiffuseColor.B, 255));
GL.LightModel(LightModelParameter.LightModelAmbient, new[] { (float)LightModel.X, (float)LightModel.Y, (float)LightModel.Z, (float)LightModel.W });
GL.Enable(EnableCap.Light0);
在这一点上,我认为其他任何事情都不一定相关,因为这是我无法正确打球的定向光。唯一的(次要)问题是 Z 坐标是反转的。
经过很多错误的开始,我得到了以下 GLSL 顶点着色器,它改编自这里的代码https://github.com/mojocorp/ShaderGen
在大多数情况下,这看起来不错,并且是我设法得到的最接近的,但它根本不对。
#version 150
precision highp int;
struct Light
{
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
vec4 lightModel;
};
struct MaterialColor
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec3 emission;
float shininess;
};
in vec3 iPosition;
in vec3 iNormal;
in vec2 iUv;
in vec4 iColor;
uniform mat4 uCurrentProjectionMatrix;
uniform mat4 uCurrentModelViewMatrix;
uniform mat4 uCurrentTextureMatrix;
uniform bool uIsLight;
uniform Light uLight;
uniform MaterialColor uMaterial;
uniform int uMaterialFlags;
out vec4 oViewPos;
out vec2 oUv;
out vec4 oColor;
out vec4 lightResult;
//Temp working colors
vec4 Ambient;
vec4 Diffuse;
vec4 Specular;
void findDirectionalLight(in vec3 normal)
{
float pf;
float nDotVP = max(0.0, dot(normal, normalize(vec3 (uLight.position))));
float nDotHV = max(0.0, dot(normal, normalize(vec3(oViewPos.xyz + uLight.position))));
if (nDotVP == 0.0)
{
pf = 0.0;
}
else
{
pf = pow(nDotHV, uMaterial.shininess);
}
Ambient += vec4(uLight.ambient, 1.0);
Diffuse += vec4(uLight.diffuse, 1.0) * nDotVP;
Specular += vec4(uLight.specular, 1.0) * pf;
}
vec4 getLightResult(in vec3 normal, in vec4 ecPosition)
{
vec4 color;
vec3 ecPosition3;
vec3 eye;
ecPosition3 = (vec3 (ecPosition)) / ecPosition.w;
eye = vec3 (0.0, 0.0, 1.0);
Ambient = vec4 (0.0);
Diffuse = vec4 (0.0);
Specular = vec4 (0.0);
findDirectionalLight(normal);
vec4 sceneColor = uLight.lightModel;
if((uMaterialFlags & 1) != 0)
{
sceneColor = vec4(uMaterial.emission, 1.0) + uMaterial.ambient * uLight.lightModel;
}
color = sceneColor + Ambient * uMaterial.ambient + Diffuse * uMaterial.specular;
color += Specular * uMaterial.specular;
color = clamp(color, 0.0, 1.0);
return color;
}
void main()
{
oViewPos = uCurrentModelViewMatrix * vec4(vec3(iPosition.x, iPosition.y, -iPosition.z), 1.0);
gl_Position = uCurrentProjectionMatrix * oViewPos;
vec3 eyeNormal = normalize(mat3(transpose(inverse(uCurrentModelViewMatrix))) * vec3(iNormal.x, iNormal.y, -iNormal.z));
vec3 eyePosition = vec3(uCurrentModelViewMatrix * vec4(iPosition.x, iPosition.y, -iPosition.z, 1.0));
oUv = (uCurrentTextureMatrix * vec4(iUv, 1.0, 1.0)).xy;
oColor = iColor;
if (uIsLight)
{
lightResult = getLightResult(eyeNormal, oViewPos);
}
else
{
lightResult = uMaterial.ambient;
}
oColor.rgb *= oColor.a;
}
片段着色器如下:
#version 150
in vec4 oViewPos;
in vec2 oUv;
in vec4 oColor;
in vec4 lightResult;
uniform bool uIsTexture;
uniform sampler2D uTexture;
uniform float uBrightness;
uniform float uOpacity;
uniform bool uIsFog;
uniform float uFogStart;
uniform float uFogEnd;
uniform vec3 uFogColor;
uniform int uMaterialFlags;
void main(void)
{
vec4 textureColor = vec4(1.0);
if(uIsTexture)
{
textureColor *= texture2D(uTexture, oUv);
if((uMaterialFlags & 1) == 0 && (uMaterialFlags & 4) == 0)
{
//Material is not emissive and lighting is enabled, so multiply by brightness
textureColor.rgb *= uBrightness;
}
}
vec4 finalColor = vec4(((textureColor.rgb) * 1.0) + (oColor.rgb * (1 - textureColor.a)), textureColor.a * uOpacity);
//Apply the lighting results *after* the final color has been calculated
if((uMaterialFlags & 4) == 0)
{
//Lighting is enabled, so multiply by light result
finalColor *= lightResult;
}
// Fog
float fogFactor = 1.0;
if (uIsFog)
{
fogFactor *= clamp((uFogEnd - length(oViewPos)) / (uFogEnd - uFogStart), 0.0, 1.0);
}
gl_FragData[0] = vec4(mix(uFogColor, finalColor.rgb, fogFactor), finalColor.a);
}
两者可能都可以进行优化,并且有一些冗余代码,我已经转储了与其他灯等有关的东西,我们目前没有使用,但我正在努力让这件事首先正常工作!
(这是一个相当大的开源游戏的一部分;很高兴提供 Github 链接等。如果您愿意提供修复而不是试图解释我可能出错的多种方式,或者如果您想要完整的测试环境)
代码注释:
- uLight统一在绘制调用开始时设置一次,使用与立即模式代码相同的属性。
- MaterialFlags 是按位设置的材质属性;1 是发光的,4 绘制不发光的材料。(两者都工作正常)
- 我已经尝试通过视图矩阵来转换灯光位置,但在所有情况下都不会产生正确的结果。
- 所有矩阵等都在两个渲染路径之间共享,因此不应该是矩阵数学不好的情况。
解决方案
推荐阅读
- php - 在 PHP 中使用 Imagick 将图像包裹在圆柱体上
- python - 如何在此散点图中添加线性回归线?
- docker - SwiftyBeaver 失败的 Vapor Linux 构建
- ios - Swift iOS:如何为使用标签系统创建的标签赋值
- git - 如何使用 Groovy 列出组织下的所有 Git 存储库?
- java - 如何装饰 httpclient 以使用 oauth 身份验证发送请求?
- javascript - 检查代理的 Discord Bot 给出了一个有趣的错误
- python - 计算python中“多个图像”中的白色像素
- typescript - TypeScript 中的 Firebase Cloud Function CORS 问题
- sql-server - 导出 excel-ssrs 上的分页符