GLSL シェーダーを使用するプログラムに取り組んでいます。2 つの異なる方法で ADS (アンビエント + ディフューズ + スペキュラー) シェーディングを計算する 2 つの異なる方法をコーディングしました。この仕事を適切に行うために、サブルーチンを使用して、いずれかの方法を使用して ADS シェーディングを計算しました。
フラグメント シェーダー コードの一部を次に示します。
subroutine vec3 LightShadingEffectType(int idx, vec3 normal, vec3 lightDir);
subroutine uniform LightShadingEffectType LightShadingEffect;
subroutine (LightShadingEffectType)
vec3 Basic_ADS_Shading(int idx, vec3 normal, vec3 lightDir)
{
vec3 reflectDir = reflect(-lightDir, normal);
vec3 viewDir = normalize(-Position.xyz);
vec3 Ambient = LightInfos[idx].La * MaterialInfos.Ka;
vec3 Diffuse = LightInfos[idx].Ld * MaterialInfos.Kd * max(dot(lightDir, normal), 0.0f);
vec3 Specular = LightInfos[idx].Ls * MaterialInfos.Ks * pow(max(dot(reflectDir, viewDir), 0.0f), MaterialInfos.Shininess);
vec3 Emissive = MaterialInfos.Ke;
return (Ambient + Diffuse + Specular + Emissive);
}
subroutine (LightShadingEffectType)
vec3 Phong_ADS_Shading(int idx, vec3 normal, vec3 lightDir)
{
vec3 v = normalize(vec3(-Position));
vec3 h = normalize(v + lightDir);
vec3 Ambient = LightInfos[idx].La * MaterialInfos.Ka;
vec3 Diffuse = LightInfos[idx].Ld * MaterialInfos.Kd * max(dot(lightDir, normal), 0.0f);
vec3 Specular = LightInfos[idx].Ls * MaterialInfos.Ks * pow(max(dot(h, normal), 0.0f), MaterialInfos.Shininess);
vec3 Emissive = MaterialInfos.Ke;
return (Ambient + Diffuse + Specular + Emissive);
}
そしてC++コード:
type::uint32 basic_ads_idx = glGetSubroutineIndex(program->getHandle(), GL_FRAGMENT_SHADER, "Basic_ADS_Shading");
type::uint32 phong_ads_idx = glGetSubroutineIndex(program->getHandle(), GL_FRAGMENT_SHADER, "Phong_ADS_Shading");
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &phong_ads_idx);
ここまで表示は正しいです。この場合、2 番目のサブルーチン定義 (Phong_ADS_Shading 呼び出し) を実行することにしました。
しかし、テクスチャを管理するためにプログラムで別のサブルーチン型を宣言したいと考えています (シグネチャは同じではありません)。(同じシェーダー内の) フラグメント シェーダー コードの別の部分を次に示します。
subroutine vec4 TexturedShadingType();
subroutine uniform TexturedShadingType TexturedShading;
subroutine (TexturedShadingType)
vec4 Textured_Shading(void)
{
vec4 TexColor = texture(Tex1, TexCoords);
return (vec4(getLightIntensity(), 1.0f) * TexColor);
}
subroutine (TexturedShadingType)
vec4 Untextured_Shading(void)
{
return (vec4(getLightIntensity(), 1.0f));
}
最後に、私の C++ コードは次のとおりです。
type::uint32 basic_ads_idx = glGetSubroutineIndex(program->getHandle(), GL_FRAGMENT_SHADER, "Basic_ADS_Shading");
type::uint32 phong_ads_idx = glGetSubroutineIndex(program->getHandle(), GL_FRAGMENT_SHADER, "Phong_ADS_Shading");
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &phong_ads_idx);
type::uint32 textured_idx = glGetSubroutineIndex(program->getHandle(), GL_FRAGMENT_SHADER, "Textured_Shading");
type::uint32 untextured_idx = glGetSubroutineIndex(program->getHandle(), GL_FRAGMENT_SHADER, "Untextured_Shading");
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &untextured_idx);
各サブルーチン index の値は次のとおりです。
std::cout << phong_idx << ", " << blinn_phong_idx << ", " << textured_idx << ", " << untextured_idx << std::endl;
-> 1, 0, 4294967295, 4294967295
最初の 2 つの値は正しいようですが、他の 2 つの値は正しいようです。
私の問題をよりよく理解するために、フラグメントシェーダーコード全体を次に示します。
#version 400
in vec3 Position;
in vec3 Normal;
in vec2 TexCoords;
layout (location = 0) out vec4 FragColor;
uniform sampler2D Tex1;
uniform int lightCount;
struct PointLight
{
vec4 Position;
vec3 La, Ld, Ls;
float Kc, Kl, Kq;
vec3 direction;
float exponent;
float cutoff;
int type;
};
struct Material
{
vec3 Ka, Kd, Ks, Ke;
float Shininess;
};
uniform PointLight LightInfos[10];
uniform Material MaterialInfos;
subroutine vec3 LightShadingEffectType(int idx, vec3 normal, vec3 lightDir);
subroutine uniform LightShadingEffectType LightShadingEffect;
subroutine (LightShadingEffectType)
vec3 Phong_Shading(int idx, vec3 normal, vec3 lightDir)
{
vec3 reflectDir = reflect(-lightDir, normal);
vec3 viewDir = normalize(-Position.xyz);
vec3 Ambient = LightInfos[idx].La * MaterialInfos.Ka;
vec3 Diffuse = LightInfos[idx].Ld * MaterialInfos.Kd * max(dot(lightDir, normal), 0.0f);
vec3 Specular = LightInfos[idx].Ls * MaterialInfos.Ks * pow(max(dot(reflectDir, viewDir), 0.0f), MaterialInfos.Shininess);
vec3 Emissive = MaterialInfos.Ke;
return (Ambient + Diffuse + Specular + Emissive);
}
subroutine (LightShadingEffectType)
vec3 Blinn_Phong_Shading(int idx, vec3 normal, vec3 lightDir)
{
vec3 v = normalize(vec3(-Position));
vec3 h = normalize(v + lightDir);
vec3 Ambient = LightInfos[idx].La * MaterialInfos.Ka;
vec3 Diffuse = LightInfos[idx].Ld * MaterialInfos.Kd * max(dot(lightDir, normal), 0.0f);
vec3 Specular = LightInfos[idx].Ls * MaterialInfos.Ks * pow(max(dot(h, normal), 0.0f), MaterialInfos.Shininess);
vec3 Emissive = MaterialInfos.Ke;
return (Ambient + Diffuse + Specular + Emissive);
}
float getLightAttenuation(vec3 lightDir, PointLight light)
{
float lightAtt = 0.0f;
float dist = 0.0f;
dist = length(lightDir);
lightAtt = 1.0f / (light.Kc + (light.Kl * dist) + (light.Kq * pow(dist, 2)));
return (lightAtt);
}
float getSpotFactor(vec3 lightDir, vec3 spotDir, PointLight light)
{
return (pow(dot(-lightDir, spotDir), light.exponent));
}
vec3 Spot_ADS_Shading(float lightAtt, vec3 tnorm, vec3 lightDirNorm, int idx)
{
vec3 LightIntensity = vec3(0.0f);
vec3 spotDirNorm = normalize(LightInfos[idx].direction);
float angle = acos(dot(-lightDirNorm, spotDirNorm));
float cutoff = radians(clamp(LightInfos[idx].cutoff, 0.0f, 90.0f));
if (angle < cutoff)
{
float spotFactor = getSpotFactor(lightDirNorm, spotDirNorm, LightInfos[idx]);
LightIntensity = lightAtt * spotFactor * LightShadingEffect(idx, -tnorm, lightDirNorm);
}
else
{
LightIntensity = LightShadingEffect(idx, -tnorm, lightDirNorm) * MaterialInfos.Ka;
}
return (LightIntensity);
}
vec3 Point_ADS_Shading(float lightAtt, vec3 tnorm, vec3 lightDirNorm, int idx)
{
return (lightAtt * LightShadingEffect(idx, tnorm, lightDirNorm));
}
vec3 getLightIntensity(void)
{
vec3 LightIntensity = vec3(0.0f);
for (int idx = 0; idx < lightCount; idx++)
{
vec3 tnorm = (gl_FrontFacing ? -normalize(Normal) : normalize(Normal));
vec3 lightDir = vec3(LightInfos[idx].Position) - Position;
vec3 lightDirNorm = normalize(lightDir);
float lightAtt = getLightAttenuation(lightDir, LightInfos[idx]);
if (LightInfos[idx].type == 1)
{
LightIntensity += Spot_ADS_Shading(lightAtt, tnorm, lightDirNorm, idx);
}
else
{
LightIntensity += Point_ADS_Shading(lightAtt, -tnorm, lightDirNorm, idx);
}
}
return (LightIntensity);
}
subroutine vec4 TexturedShadingType();
subroutine uniform TexturedShadingType TexturedShading;
subroutine (TexturedShadingType)
vec4 Textured_Shading(void)
{
vec4 TexColor = texture(Tex1, TexCoords);
return (vec4(getLightIntensity(), 1.0f) * TexColor);
}
subroutine (TexturedShadingType)
vec4 Untextured_Shading(void)
{
return (vec4(getLightIntensity(), 1.0f));
}
void main(void)
{
FragColor = TexturedShading();
}
問題は、ジオメトリが黒でレンダリングされることです。2 つの均一なサブルーチンの間に矛盾があると思います。道に迷いました。誰でも私を助けることができますか?