OpenGLの照明システムを使用せずにすばらしい照明を実装するための探求を開始しました。 Phong拡散照明を正常に実装しました。スペキュラは私にトラブルを与えている。GLSL/OpenGL 2.1:ユニフォームを使用した鏡面照明
私は使用しているOpenGL定数が占有しているスペースが何であるかを知る必要があります。なぜなら、それらは誤って変換されているようであり、照明グリッチが発生するからです。
Phong拡散シェーダを正常に読み込んで実行すると、C++コードに問題はないことが確認されました。しかし、C++コードは無効なデータをシェーダに渡すことがありますが、これは私が心配していることの1つです。私はシェイダーにコメントを貼り付けるだけでなく、シェイダーに直接関連するすべてのC++コードを貼り付けます(問題はシェーダーに90%確実です)。
これらの画像では、光源は大きな点であり、軸が示されています。 ライトはicosphereの周りでy = 0で回転しています。あなたはモデルが何であるかのアイデア...私はピクセルごとまだ行っていない 注意を...ソースに示すよう
はここで、フレネル照明のgetのではここで、びまん性です。 .. 点灯面が光とカメラここ
の間ではないどこかに、光に直面しているか 注意が再び私は30で乗算しなければならなかったブリン・フォン、... 注意ですか照明された面は光源の方を向いており、私はこの
バーテックスシェーダソース(「dirlight.vs」からロード)
const int MAXLIGHTS = 4;
uniform bool justcolor = false;
uniform int lightcount;
uniform vec4 lightposs[MAXLIGHTS];
uniform vec4 lightdirs[MAXLIGHTS];
uniform vec4 lightdifs[MAXLIGHTS];
uniform vec4 lightambs[MAXLIGHTS];
//diffuse
vec4 D;
//specular, normaldotlight
float S, NdotL[MAXLIGHTS];
//normal, eyevec, lightvecs, halfvecs
vec3 N, E, L[MAXLIGHTS], H[MAXLIGHTS];
void main() {
//if(lightcount > MAXLIGHTS) lightcount = MAXLIGHTS;
D = vec4(0.0, 0.0, 0.0, 0.0);
S = 0.0;
N = gl_Normal;
E = normalize(vec3(-gl_Vertex));
for(int i = 0; i < lightcount; i++)
{
//calculating direction to light source
L[i] = normalize(vec3(lightposs[i] - gl_Vertex));
//normal dotted with direction to light source
NdotL[i] = max(dot(N, L[i]), 0.0);
//diffuse term, works just fine
D += gl_Color * lightdifs[i] * NdotL[i];
if(NdotL[i] >= 0.0)
{
//halfvector = normalize(lightdir + eyedir)
H[i] = normalize(L[i] + E);
//Blinn-Phong, only lights up faces whose normals
//point directly to the light source for some reason...
//S += max(0.0, dot(H[i], N));
//Fresnel, lights up more than Blinn-Phong
//but the faces still point directly to the light source,
//not somewhere between the lightsource and myself, like they should.
S += pow(max(0.0, dot(reflect(L[i], N), E)), 50.0);
}
else
{
H[i] = vec3(0.0, 0.0, 0.0);
}
}
//currently only showing specular. To show diffuse add D.
gl_FrontColor = justcolor ? gl_Color : vec4(S * 0.3, S * 0.3, S * 0.3, 1.0);
gl_Position = ftransform();
}
フラグメントシェーダソース(dirlight」からロードを達成するために30で鏡面係数(S)を乗算しなければならなかったことも事実C++メインの初期化...
//class program manages shaders
Program shaders = Program();
//attach a vertex shader, compiled from source in dirlight.vs
shaders.addShaderFile(GL_VERTEX_SHADER, "dirlight.vs");
//attach a fragment shader compiled from source in dirlight.fs
shaders.addShaderFile(GL_FRAGMENT_SHADER, "dirlight.fs");
//link program
shaders.link();
//use program
shaders.use();
//Program::getUniformLoc(const char* name) grabs the location
//of the uniform specified
GLint sTime = shaders.getUniformLoc("time");
GLint lightcount = shaders.getUniformLoc("lightcount");
GLint lightdir = shaders.getUniformLoc("lightdirs");
GLint lightdif = shaders.getUniformLoc("lightdifs");
GLint lightamb = shaders.getUniformLoc("lightambs");
GLint lightpos = shaders.getUniformLoc("lightposs");
GLint justcolor = shaders.getUniformLoc("justcolor");
glUniform1i(justcolor, 0);
glUniform1i(lightcount, 2);
//diffuse light colors
GLfloat lightdifs[] = {1.f, 1.f, 1.f, 1.f,
1.f, 1.f, 1.f, 1.f};
glUniform4fv(lightdif, 2, lightdifs);
glUniform4f(lightamb, 0.4f, 0.4f, 0.4f, 1.f);
Excerから.fs ")
void main()
{
gl_FragColor = gl_Color;
}
抜粋C++メインループからのpt ...
//My lights rotate around the origin, where I have placed an icosphere
GLfloat lightposs[] = {-4 * sinf(newTime), lighth, -4 * cosf(newTime), 0.0f,
-4 * sinf(newTime + M_PI), lighth, -4 * cosf(newTime + M_PI), 0.0f};
glUniform4fv(lightpos, 2, lightposs);
技術的には、頂点シェーダではなく、フラグメントシェーダでライティング計算を行う必要があります。それはフラグメントシェーダの重要な目的の1つです。フラグメントごとの照明モデルを実装します。 – datenwolf
私は頂点シェーダで最初に実装しているので、同じ場所にすべてを持つことができます。私は後でピクセル単位に移行しています。私はそれらの間にエラーの余地があることを望んでいない、それが私が扱っている唯一のものでない限り。 – Miles