Ces derniers jours, j'ai joué avec la foudre en Java (Libgdx). Je suis nouveau à OpenGL ou Shaders et j'ai trébuché à travers un joli tutoriel comment mettre en œuvre l'éclairage avec le mappage normal (https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson6). Jusqu'à présent, j'ai réussi à le faire avec une lumière et maintenant j'essaye de faire le même effet avec plusieurs lumières. J'ai essayé d'effectuer un appel de tirage pour chaque lumière avec un mélange additif. Les ombres dessinent correctement, mais chaque fois que j'ajoute une lumière, la couleur ambiante devient plus claire. J'ai essayé quelques petites choses mais rien n'a fonctionné et je suis coincé.La lumière ambiante devient plus claire quand une lumière est ajoutée (OpenGL, cartographie normale)
Mon rendre les méthodes:
@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();
}
Et voici mon shader fragment:
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);
}
Cela dépend de votre définition de la lumière ambiante. Si chacune de vos sources de lumière "émet" de la lumière ambiante, alors ce comportement est complètement correct. Si la lumière ambiante est une sorte de chose spéciale qui ne doit être ajoutée qu'une seule fois, elle doit être complètement supprimée du light shader et ajoutée par un draw-call/shader séparé. Juste comme un commentaire: Votre façon de rendre chaque géométrie une fois par source lumineuse est très inefficace. Envisagez plutôt d'utiliser des tableaux uniformes dans un shader. Et être autrichien n'est rien de mal :) – BDL
Merci pour votre réponse rapide :) Je viens de supprimer la lumière ambiante du shader. Comment puis-je l'implémenter maintenant, sans utiliser un autre shader? – Quentin
Vous ne pouvez pas;). Créez un second shader qui sort juste la lumière ambiante et l'utilise une fois. J'aurais dû aussi mentionner dans le premier commentaire que vous pourriez avoir un problème avec votre algorithme si vous avez des objets qui se chevauchent dans l'espace d'écran car ils pourraient ne pas être composés correctement. – BDL