Lights come from the SharpGLTF runtime, as is. This is the last shader we tried, it’s super messy, I’ll try to update with a better write up. The faulty code is the one calling the ComputeLights function, it’s the same as the XNA fx, unless something else is going on:
#version 330
// This source is subject to a License.
// Please see the license.txt file for more information.
// All other rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
@uniform:
#define SKINNED_EFFECT_MAX_BONES 128
uniform sampler2D Texture;
//uniform vec4 InputClipRectangle;
uniform vec4 DiffuseColor;
uniform vec3 EmissiveColor;
uniform vec3 SpecularColor;
uniform float SpecularPower;
uniform vec3 DirLight0Direction;
uniform vec3 DirLight0DiffuseColor;
uniform vec3 DirLight0SpecularColor;
uniform vec3 DirLight1Direction;
uniform vec3 DirLight1DiffuseColor;
uniform vec3 DirLight1SpecularColor;
uniform vec3 DirLight2Direction;
uniform vec3 DirLight2DiffuseColor;
uniform vec3 DirLight2SpecularColor;
uniform vec3 EyePosition;
uniform vec3 FogColor;
uniform vec4 FogVector;
uniform mat4 World;
uniform mat4 View;
uniform mat4 Projection;
uniform mat3 WorldInverseTranspose;
uniform mat4 WorldViewProj;
uniform float HasTexture;
uniform mat4 BoneTransforms[SKINNED_EFFECT_MAX_BONES];
uniform float IsSkinned;
@vertex_input:
layout(location = 0) in vec3 VertexPosition;
layout(location = 1) in vec3 VertexNormal;
layout(location = 2) in vec2 VertexTexCoord;
layout(location = 3) in vec4 VertexBlendIndex;
layout(location = 4) in vec4 VertexWeight;
@vertex_output:
out vec4 FragmentPositionPS;
out vec2 FragmentTexCoord;
out vec4 FragmentPositionWS;
out vec3 FragmentNormalWS;
out vec4 FragmentDiffuse;
@fragment_input:
in vec4 FragmentPositionPS;
in vec2 FragmentTexCoord;
in vec4 FragmentPositionWS;
in vec3 FragmentNormalWS;
in vec4 FragmentDiffuse;
@fragment_output:
layout(location = 0) out vec4 OutputColour;
@vertex:
mat4 transpose(in mat4 inMatrix) {
highp vec4 i0 = inMatrix[0];
highp vec4 i1 = inMatrix[1];
highp vec4 i2 = inMatrix[2];
highp vec4 i3 = inMatrix[3];
highp mat4 outMatrix = mat4(
vec4(i0.x, i1.x, i2.x, i3.x),
vec4(i0.y, i1.y, i2.y, i3.y),
vec4(i0.z, i1.z, i2.z, i3.z),
vec4(i0.w, i1.w, i2.w, i3.w)
);
return outMatrix;
}
float ComputeFogFactor(vec4 position)
{
return clamp(dot(position, FogVector), 0.0, 1.0);
}
void main()
{
if (IsSkinned == 1.0)
{
vec4 skinningPosition = vec4(0.0, 0.0, 0.0, 0.0);
float boneCount = 4;
for (int i = 0; i < boneCount; i++)
{
skinningPosition += (BoneTransforms[int(VertexBlendIndex[i])] * vec4(VertexPosition, 1.0)) * VertexWeight[i];
}
FragmentPositionPS = WorldViewProj * skinningPosition;
//FragmentPositionPS = WorldViewProj * animationMatrix * vec4(VertexPosition, 1.0);
//FragmentPositionPS = WorldViewProj * Position;
FragmentPositionWS = (World)*vec4(VertexPosition, 1.0);
FragmentNormalWS = normalize(VertexNormal);
//float FogFactor = ComputeFogFactor(vec4(VertexPosition, 1.0));
//FragmentPositionWS = vec4(VertexPosition.xyz, 1.0);
FragmentDiffuse = vec4(1, 1, 1, 1);
FragmentTexCoord = VertexTexCoord;
gl_Position = FragmentPositionPS;
}
else
{
FragmentPositionPS = WorldViewProj * vec4(VertexPosition, 1.0);
//FragmentPositionPS = WorldViewProj * Position;
FragmentPositionWS = (World)*vec4(VertexPosition, 1.0);
FragmentNormalWS = normalize(VertexNormal);
//float FogFactor = ComputeFogFactor(vec4(VertexPosition, 1.0));
//FragmentPositionWS = vec4(VertexPosition.xyz, 1.0);
FragmentDiffuse = vec4(1, 1, 1, 1);
FragmentTexCoord = VertexTexCoord;
gl_Position = FragmentPositionPS;
}
}
@fragment:
vec3 ApplyFog(vec4 color, float fogFactor)
{
return mix(color.rgb, FogColor * color.a, fogFactor);
}
vec3 AddSpecular(inout vec4 color, vec3 specular)
{
return specular * color.a;
}
struct ColorPair
{
vec3 Diffuse;
vec3 Specular;
};
mat3 transpose(mat3 m) {
return mat3(m[0][0], m[1][0], m[2][0],
m[0][1], m[1][1], m[2][1],
m[0][2], m[1][2], m[2][2]);
}
ColorPair ComputeLights(vec3 eyeVector, vec3 worldNormal, int numLights)
{
mat3 lightDirections = mat3(0);
mat3 lightDiffuse = mat3(0);
mat3 lightSpecular = mat3(0);
mat3 halfVectors = mat3(0);
for (int i = 0; i < numLights; i++)
{
lightDirections[i] = mat3(DirLight0Direction, DirLight1Direction, DirLight2Direction)[i];
lightDiffuse[i] = mat3(DirLight0DiffuseColor, DirLight1DiffuseColor, DirLight2DiffuseColor)[i];
lightSpecular[i] = mat3(DirLight0SpecularColor, DirLight1SpecularColor, DirLight2SpecularColor)[i];
halfVectors[i] = normalize(eyeVector - lightDirections[i]);
}
vec3 dotL = -((lightDirections) * worldNormal);
vec3 dotH = halfVectors * worldNormal;
vec3 zeroL = step(vec3(0, 0, 0), dotL);
vec3 diffuse = zeroL * dotL;
vec3 specular = pow(max(dotH, 0) * zeroL, vec3(SpecularPower));
ColorPair result;
result.Diffuse = (lightDiffuse * diffuse) * DiffuseColor.rgb + EmissiveColor;
result.Specular = (lightSpecular * specular) * SpecularColor;
return result;
}
void main()
{
vec4 color = vec4(1.0, 1.0, 1.0, 1.0);
if (HasTexture == 1.0)
{
color = texture2D(Texture, FragmentTexCoord);// * FragmentDiffuse;
}
vec3 lightDir = normalize(DirLight0Direction - FragmentPositionWS.xyz);
float diff = max(dot(FragmentNormalWS, lightDir), 0.0);
vec3 diffuse = diff * DirLight0DiffuseColor;
vec3 eyeVector = normalize(EyePosition - FragmentPositionWS.xyz);
vec3 worldNormal = FragmentNormalWS;//normalize(FragmentNormalWS);
ColorPair lightResult = ComputeLights(eyeVector, worldNormal, 1);
color.rgb *= lightResult.Diffuse;
color.rgb += AddSpecular(color, lightResult.Specular);
//color.rgb += ApplyFog(color, FragmentPositionWS.w);
// Multiply texture colour with blending colour
//OutputColour = color;
//OutputColour = vec4(diffuse, 1.0) * texture2D(Texture, FragmentTexCoord);
OutputColour = texture2D(Texture, FragmentTexCoord);
}