定位燈我有一個關於我的GLES 2.0 Android應用程序的移動點光源一個問題:混淆眼睛和世界空間,而在GLES 2.0
我個人的一個實例走動在一個大的表面。這個人需要在他頭頂上有一道光線才能正確照亮他周圍的一個小區域。由於燈光實例將人物實例作爲其父項,因此其在世界空間中的位置與人物移動的方式完全相同(y-Offset +4)。但是每次啓動應用程序時,光線都不會位於頂部,並且不會完全按照人物移動的方式移動(或者至少看起來不像)。即使光線和人物共享相同的x值和z值,它看起來就像是在人的面前。 人是一個立方體(沒有複雜的模型)。
這裏是我的多維數據集的繪製方法的代碼:
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 Shader代碼:
片段着色器代碼:
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));
}
我覺得它有什麼與我在輕物體的位置傳遞的方式有關......但我無法弄清楚什麼是正確的方法。
在此先感謝... :-)
================================= =========
!!編輯!我上傳了一個問題的視頻: https://dl.dropboxusercontent.com/u/17038392/opengl_lighting_test.mp4(2MB)
這個場景中的每個形狀都是一個立方體。當人站在房間中間時,燈光對地板沒有影響。如果該人移動到上角,則光線移動到房間中間。 現在這裏是非常奇怪的事情:因爲光線位於人的上方,所以當人在房間中間時照亮黃色的箱子就好了。如何發現地球可以發生? ;-)
==========================================
編輯2: 好吧,所以我試圖做你說的。但是,作爲一個新秀,我無法做正確:
我拉法的任何多維數據集實例:
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");
}
所以,我更新的頂點着色器的代碼現在是:
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;
}
我想,也許如果我倒置並轉置模型矩陣並將其保存到一個正常的矩陣,它可能已經解決了這個問題。 但我認爲我完全錯了。
嗨馬蒂奇,非常感謝你看我的代碼。對不起,沒有提供足夠的信息。我沒有想過這個......我將在稍後迴應你的問題/假設。今天一直很忙。 – AudioGuy
遊戲不是第一人稱。這很像暗黑破壞神,所以相機在角色之上。每個立方體都有它的左下角位於(0,0,0)處的模型空間。然後,立方體通過translateM()轉換爲其在世界的最終位置;場景呈現正常。現在,如果立方體在世界上(4,1,3)(因爲它的模型被翻譯成(4,1,3)),我想移動一個光線來說出4,4,3(因爲它總是需要懸停在翻譯的立方體上,所以,如果立方體在(4,1,3)處,我手動更新燈位置爲(4,4,3),這就是getLightPosInWorldSpace()返回時調用的函數。 – AudioGuy
但是在你使用它之前,我看到你正在乘以pVMatrix的位置,爲什麼?然後什麼是getLightPosInWorldSpace? –