J'ai un problème au sujet d'un point de lumière mobile dans mon GLES 2.0 application Android:oeil Confondre et dans l'espace monde tout en positionnant la lumière dans GLES 2.0
J'ai une instance de personne marchant autour sur une grande surface. Cette personne doit avoir une lumière au-dessus de sa tête afin d'éclairer correctement une petite zone autour de lui. Puisque l'instance de la lumière a pour parent l'instance de la personne, sa position dans l'espace du monde se déplace exactement comme la personne se déplace (y-Offset +4). Mais à chaque fois que je lance l'application, la lumière n'est pas positionnée sur le dessus et ne bouge pas exactement comme la personne bouge (ou du moins il semble qu'elle ne l'est pas). Il semble que c'est à gauche et devant la personne même si la lumière et la personne partagent les mêmes valeurs x et z. La personne est un cube (pas encore de modèle complexe).
Voici mon code de la méthode de tirage au sort du cube:
public void draw(float[] pPMatrix, float[] pVMatrix)
{
float[] MVPMatrix = new float[16];
Matrix.setIdentityM(getParent().getModelMatrix(),0);
Matrix.translateM(getParent().getModelMatrix(),0,mXLL, mYLL, mZLL);
Matrix.multiplyMM(MVPMatrix, 0, pVMatrix, 0, getParent().getModelMatrix(), 0);
Matrix.multiplyMM(MVPMatrix, 0, pPMatrix, 0, MVPMatrix, 0);
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// .....
GLES20.glUniformMatrix4fv(LightingProgram.getMVPMatrixHandle(), 1, false, MVPMatrix, 0);
GLES20.glUniformMatrix4fv(LightingProgram.getMVMatrixHandle(), 1, false, pVMatrix, 0);
LightObject lo = mParent.getWorld().getLightObjects().get(0);
Matrix.multiplyMV(lo.getLightPosInEyeSpace(), 0, pVMatrix, 0, lo.getLightPosInWorldSpace(), 0);
GLES20.glUniform3f(LightingProgram.getLightPosHandle(), lo.getLightPosInEyeSpace()[0], lo.getLightPosInEyeSpace()[1], lo.getLightPosInEyeSpace()[2]);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, mVertexCount);
}
Vertex Code Shader est:
Fragment Code Shader est:
precision mediump float;
uniform vec3 u_LightPos;
uniform sampler2D u_Texture;
varying vec3 v_Position;
varying vec4 v_Color;
varying vec3 v_Normal
varying vec2 v_TexCoordinate;
void main()
{
float distance = length(u_LightPos - v_Position);
// Get a lighting direction vector from the light to the vertex.
vec3 lightVector = normalize(u_LightPos - v_Position);
float diffuse = max(dot(v_Normal, lightVector), 0.0);
diffuse = diffuse * (1.0/(1.0 + (0.25 * distance)));
// Add ambient lighting
diffuse = diffuse + 0.25;
gl_FragColor = (diffuse * v_Color * texture2D(u_Texture, v_TexCoordinate));
}
Je pense qu'il a quelque chose à voir avec la façon dont je passe dans la position de l'objet lumineux ... mais je n'arrive pas à comprendre quelle est la bonne façon.
Merci à l'avance ... :-)
================================= =========
!! ÉDITER !! J'ai téléchargé une vidéo du problème: https://dl.dropboxusercontent.com/u/17038392/opengl_lighting_test.mp4 (2MB)
Chaque forme de cette scène est un cube. Lorsque la personne se tient au milieu de la pièce, la lumière n'a aucun effet sur le sol. Si la personne se déplace dans le coin supérieur, la lumière se déplace vers le milieu de la pièce. Maintenant, voici la chose très étrange: puisque la lumière est positionnée au-dessus de la personne, elle illumine les caisses jaunes quand la personne est au milieu de la pièce. COMMENT LA TERRE PEUT-ELLE SE PRODUIRE? ;-)
=====================================
EDIT 2: Ok, donc j'ai essayé de faire ce que vous avez dit. Mais, étant une recrue, je ne parviens pas à le faire correctement:
Mon tirage Méthode pour toute instance de cube:
public void draw(float[] pPMatrix, float[] pVMatrix)
{
float[] MVPMatrix = new float[16];
float[] normalVMatrix = new float[16];
float[] normalTransposed = new float[16];
// Move object
Matrix.setIdentityM(getParent().getModelMatrix(),0);
Matrix.translateM(getParent().getModelMatrix(),0,mXLL, mYLL, mZLL);
Matrix.multiplyMM(MVPMatrix, 0, pVMatrix, 0, getParent().getModelMatrix(), 0);
Matrix.multiplyMM(MVPMatrix, 0, pPMatrix, 0, MVPMatrix, 0);
// create normal matrix by inverting and transposing the modelmatrix
Matrix.invertM(normalVMatrix, 0, getParent().getModelMatrix(), 0);
Matrix.transposeM(normalTransposed, 0, normalVMatrix, 0);
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// ============================
// POSITION
// ============================
getVertexBuffer().position(0);
GLES20.glVertexAttribPointer(LightingProgram.getPositionHandle(), COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, getVertexBuffer());
GLES20.glEnableVertexAttribArray(LightingProgram.getPositionHandle());
// ============================
// COLOR
// ============================
getColorBuffer().position(0);
GLES20.glVertexAttribPointer(LightingProgram.getColorHandle(), COLOR_DATA_SIZE, GLES20.GL_FLOAT, false, 0, getColorBuffer());
GLES20.glEnableVertexAttribArray(LightingProgram.getColorHandle());
// ============================
// NORMALS
// ============================
// Pass in the normal information
if(LightingProgram.getNormalHandle() != -1)
{
getNormalBuffer().position(0);
GLES20.glVertexAttribPointer(LightingProgram.getNormalHandle(), NORMAL_DATA_SIZE, GLES20.GL_FLOAT, false, 0, getNormalBuffer());
GLES20.glEnableVertexAttribArray(LightingProgram.getNormalHandle());
checkGLError("normals");
}
// ============================
// TEXTURE
// ============================
// Set the active texture unit to texture unit 0.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
// Bind the texture to this unit.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, getTextureHandle());
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
//GLES20.glUniform1i(mTextureUniformHandle, 0);
GLES20.glUniform1i(LightingProgram.getTextureUniformHandle(), 0);
getTextureBuffer().position(0);
GLES20.glVertexAttribPointer(LightingProgram.getTextureCoordinateHandle(), TEXTURE_DATA_SIZE, GLES20.GL_FLOAT, false, 0, getTextureBuffer());
GLES20.glEnableVertexAttribArray(LightingProgram.getTextureCoordinateHandle());
// Pass the projection and view transformation to the shader
GLES20.glUniformMatrix4fv(LightingProgram.getMVPMatrixHandle(), 1, false, MVPMatrix, 0);
GLES20.glUniformMatrix4fv(LightingProgram.getMVMatrixHandle(), 1, false, pVMatrix, 0);
GLES20.glUniformMatrix4fv(LightingProgram.getNormalHandle(), 1, false, normalTransposed, 0);
LightObject lo = mParent.getWorld().getLightObjects().get(0);
Matrix.multiplyMV(lo.getLightPosInEyeSpace(), 0, pVMatrix, 0, lo.getLightPosInWorldSpace(), 0);
GLES20.glUniform3f(LightingProgram.getLightPosHandle(), lo.getLightPosInEyeSpace()[0], lo.getLightPosInEyeSpace()[1], lo.getLightPosInEyeSpace()[2]);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, mVertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(LightingProgram.getPositionHandle());
GLES20.glDisableVertexAttribArray(LightingProgram.getTextureCoordinateHandle());
if(LightingProgram.getNormalHandle() != -1)
GLES20.glDisableVertexAttribArray(LightingProgram.getNormalHandle());
GLES20.glDisableVertexAttribArray(LightingProgram.getColorHandle());
checkGLError("end");
}
Alors, mon code de vertex shaders mis à jour est maintenant:
uniform mat4 u_MVPMatrix; // A constant representing the combined model/view/projection matrix.
uniform mat4 u_MVMatrix; // A constant representing the combined model/view matrix.
uniform mat4 u_NMatrix; // combined normal/view matrix ???
attribute vec4 a_Position; // Per-vertex position information we will pass in.
attribute vec4 a_Color; // Per-vertex color information we will pass in.
attribute vec3 a_Normal; // Per-vertex normal information we will pass in.
attribute vec2 a_TexCoordinate; // Per-vertex texture coordinate information we will pass in.
varying vec3 v_Position; // This will be passed into the fragment shader.
varying vec4 v_Color; // This will be passed into the fragment shader.
varying vec3 v_Normal; // This will be passed into the fragment shader.
varying vec2 v_TexCoordinate; // This will be passed into the fragment shader.
// The entry point for our vertex shader.
void main()
{
// Transform the vertex into eye space.
v_Position = vec3(u_MVMatrix * a_Position);
// Pass through the color.
v_Color = a_Color;
// Pass through the texture coordinate.
v_TexCoordinate = a_TexCoordinate;
// Transform the normal's orientation into eye space.
v_Normal = vec3(u_NMatrix * vec4(a_Normal, 0.0)); // THIS does not look right...
//v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0));
// gl_Position is a special variable used to store the final position.
// Multiply the vertex by the matrix to get the final point in normalized screen coordinates.
gl_Position = u_MVPMatrix * a_Position;
}
Je pensais que peut-être si j'inversais et transposais la matrice du modèle et sauvegardais cela dans une matrice normale, cela pourrait peut-être régler le problème. Mais je pense que je l'ai eu complètement faux ..
Salut Matic, merci beaucoup d'avoir regardé mon code. Désolé de ne pas fournir suffisamment d'informations. Je n'ai pas pensé à cela ... Je vais répondre à vos questions/hypothèses plus tard. J'ai été occupé aujourd'hui. – AudioGuy
Le jeu n'est pas la 1ère personne. C'est un peu comme Diablo, donc la caméra est au-dessus du personnage. Chaque cube a son espace modèle où sa partie inférieure gauche est à (0,0,0). Ensuite, le cube est traduit à sa position finale dans le monde avec translateM(); La scène se passe bien. Maintenant, si le cube est à (4,1,3) dans le monde (parce que son modèle a été traduit en (4,1,3)), je veux déplacer une lumière pour dire 4,4,3 (parce que toujours Donc, si le cube est à (4,1,3), je mets à jour manuellement la position des lumières à (4, 4, 3) .C'est ce que getLightPosInWorldSpace() retourne sur appel – AudioGuy
I Mais avant de l'utiliser, je vois que vous multipliez la position par pVMatrix Pourquoi? Et puis, qu'est-ce que getLightPosInWorldSpace? –