首页 > 解决方案 > 在 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 链接等。如果您愿意提供修复而不是试图解释我可能出错的多种方式,或者如果您想要完整的测试环境)

代码注释:

标签: c#openglglsllighting

解决方案


推荐阅读