最後の数日間、私はJava(Libgdx)で稲妻で遊んでいました。私はOpenGLやShadersを初めて使っています。普通のマッピング(https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson6)でライティングを実装する方法については、チュートリアルを見つけました。今まで私は1つのライトでこれをやっていましたが、今は複数のライトで同じ効果を出そうとしています。私は、追加のブレンドを使用して各ライトに対して1回の描画呼び出しを実行しようとしました。影は正しく描画されていますが、ライトを追加するたびに周囲の色が明るくなります。私はいくつかのことを試みたが、何も働かず、私は立ち往生している。ライトが追加されると周囲光が明るくなります(OpenGL、ノーマルマッピング)
レンダリングマイ方法:ここ
@Override
public void render() {
renderToFbo(Gdx.input.getX(), Gdx.graphics.getHeight() - Gdx.input.getY());
renderToScreen(Gdx.input.getX(), Gdx.graphics.getHeight() - Gdx.input.getY());
renderToFbo(200, 200);
batch.setBlendFunction(GL_ONE,GL_ONE_MINUS_SRC_COLOR);
renderToScreen(200,200);
renderToFbo(500, 500);
batch.setBlendFunction(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
renderToScreen(500,500);
}
private void renderToFbo(float posX, float posY){
fbo.begin();
batch.setBlendFunction(GL_ONE, GL_ZERO);
batch.setShader(defaultShader);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(lightMap, posX - lightSize/2, posY - lightSize/2, lightSize,lightSize);
batch.end();
fbo.end();
}
private void renderToScreen(float posX, float posY){
batch.setShader(lightningShader);
batch.begin();
float x = posX/(float) Gdx.graphics.getWidth();
float y = posY/(float) Gdx.graphics.getHeight();
LIGHT_POS.x = x;
LIGHT_POS.y = y;
lightningShader.setUniformf("lightPos", LIGHT_POS.x, LIGHT_POS.y, LIGHT_POS.z);
fbo.getColorBufferTexture().bind(2);
normalMap.bind(1);
texture.bind(0);
batch.draw(texture, 0,0);
batch.end();
}
そして、私のフラグメントシェーダ:
varying vec4 vColor;
varying vec2 vTexCoord;
uniform sampler2D u_texture; //diffuse map
uniform sampler2D u_normals; //normal map
uniform sampler2D u_light; //light map
uniform vec2 resolution; //resolution of screen
uniform vec3 lightPos; //light position, normalized
uniform vec4 lightColor; //light RGBA -- alpha is intensity
uniform vec4 ambientColor; //ambient RGBA -- alpha is intensity
void main() {
//RGBA of our diffuse color
vec4 diffuseColor = texture2D(u_texture, vTexCoord);
//RGB of our normal map
vec3 normalMap = texture2D(u_normals, vTexCoord).rgb;
//NormalMap.g = 1.0 - NormalMap.g;
//The delta position of light
vec3 lightDir = vec3(lightPos.xy - (gl_FragCoord.xy/resolution.xy), lightPos.z);
lightDir.x *= resolution.x/resolution.y;
//normalize our vectors
vec3 N = normalize(normalMap * 2.0 - 1.0);
vec3 L = normalize(lightDir);
//Pre-multiply light color with intensity
//Then perform "N dot L" to determine our diffuse term
vec3 diffuse = (lightColor.rgb * lightColor.a) * max(dot(N, L), 0.0);
//pre-multiply ambient color with intensity
vec3 ambient = ambientColor.rgb * ambientColor.a;
//calculate attenuation from lightmap
vec2 lighCoord = (gl_FragCoord.xy/resolution.xy);
vec3 attenuation = texture2D(u_light, lighCoord).rgb;
//the calculation which brings it all together
vec3 intensity = ambient + diffuse * attenuation;
vec3 finalColor = diffuseColor.rgb * intensity;
gl_FragColor = vColor * vec4(finalColor, diffuseColor.a);
}
それは、周囲光のあなたの定義に依存します。それぞれの光源が周囲光を「放射」する場合、この動作は完全に良好です。アンビエントライトが特殊なものであれば、一度しか追加しないと、ライトシェーダから完全に削除し、別の描画コール/シェーダで追加する必要があります。コメントと同じように、光源ごとに1回ずつすべてのジオメトリをレンダリングする方法は非常に非効率的です。 1つのシェーダで均一な配列を使用することを検討してください。そしてオーストリア人は何も悪いことはありません:) – BDL
あなたの素早い返答をありがとう:)私はちょうどシェーダから環境光を削除しました。他のシェーダを使用せずに、今すぐ実装する方法はありますか? – Quentin
できません。周囲の光を出力して一度しか使用しない第2のシェーダを作成します。最初のコメントでは、オブジェクトが正しく構成されていない可能性があるため、スクリーンスペースにオブジェクトが重なっていると、アルゴリズムに問題が発生する可能性があります。 – BDL