OpenGL ES 2.0 漫射照明:模型显示为黑色
OpenGL ES 2.0 diffuse lighting: model shows up black
这个问题困扰了我一个星期左右...
我试图加载 stl 文件并将其显示在屏幕上。文件已正确读取。不添加光的渲染非常好。添加光照和着色器代码后,模型还在,但变黑了。
我按照本文下面从 link 下载的示例进行操作:
http://www.learnopengles.com/android-lesson-two-ambient-and-diffuse-lighting/
着色器代码与示例完全相同。程序 link 没问题。着色器编译也很好。我找不到问题出在哪里。 PLZ帮帮我。
我的渲染器:
public class MyGLRenderer implements GLSurfaceView.Renderer {
private Test test;
private Light1 light1;
private float range = 145;
private final float[] mMVMMatrix = new float[16];
private final float[] mMVPMatrix = new float[16];
private final float[] mModelMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
protected final static float[] mLightPosInEyeSpace = new float[4];
private final float[] mLightModelMatrix = new float[16];
private final float[] mLightPosInModelSpace = new float[] {0.0f, 0.0f, 0.0f, 1.0f};
private final float[] mLightPosInWorldSpace = new float[4];
private final float[] mTempMatrix = new float[16];
public static final float[] mAccumulatedMatrix = new float[16];
private final float[] mCurrMatrix = new float[16];
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthFunc(GLES20.GL_LEQUAL);
Matrix.setIdentityM(mTempMatrix, 0);
Matrix.setIdentityM(mAccumulatedMatrix, 0);
light1 = new Light1();
test = new Test();
}
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setIdentityM(mViewMatrix, 0);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.setIdentityM(mCurrMatrix, 0);
Matrix.setIdentityM(mLightModelMatrix, 0);
Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0, mLightPosInModelSpace, 0);
Matrix.multiplyMV(mLightPosInEyeSpace, 0, mViewMatrix, 0, mLightPosInWorldSpace, 0);
Matrix.rotateM(mCurrMatrix, 0, mAngleY, 0.0f, 1.0f, 0.0f);
Matrix.rotateM(mCurrMatrix, 0, mAngleX, 1.0f, 0, 0.0f);
mAngleX = 0.0f;
mAngleY = 0.0f;
Matrix.multiplyMM(mTempMatrix, 0, mCurrMatrix, 0, mAccumulatedMatrix, 0);
System.arraycopy(mTempMatrix, 0, mAccumulatedMatrix, 0, 16);
Matrix.multiplyMM(mTempMatrix, 0, mModelMatrix, 0, mAccumulatedMatrix, 0);
System.arraycopy(mTempMatrix, 0, mModelMatrix, 0, 16);
Matrix.translateM(mModelMatrix, 0, -test.meanX, -test.meanY, -test.meanZ);
Matrix.multiplyMM(mMVMMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVMMatrix, 0);
light1.draw(mMVPMatrix);
test.draw(mMVPMatrix, mMVMMatrix);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.orthoM(mProjectionMatrix, 0, -range*ratio, range*ratio, -range, range, -range, range);
}
public final static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public static volatile float mAngleX;
public static volatile float mAngleY;
public static void setAngleX(float angle) {mAngleX = angle;}
public float getAngleX() {
return mAngleX;
}
public static void setAngleY(float angle) {
mAngleY = angle;
}
public float getAngleY() {
return mAngleY;
}}
我用来绘制光线位置的代码:
public class Light1 {
private final String vertexShaderCode =
"uniform mat4 u_MVPMatrix; \n"
+ "attribute vec4 a_Position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_MVPMatrix \n"
+ " * a_Position; \n"
+ " gl_PointSize = 5.0; \n"
+ "} \n";
private final String fragmentShaderCode =
"precision mediump float; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4(1.0, \n"
+ " 1.0, 1.0, 1.0); \n"
+ "} \n";
//Light*******************
public static float[] lightLocation = new float[] {150, 150, 0};//*********ok
private final int mProgram;
//Light*******************
public Light1() {
// initialize byte buffer for the draw list
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
}
public void draw(float[] mvpMatrix) {
GLES20.glUseProgram(mProgram);
final int pointMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");
final int pointPositionHandle = GLES20.glGetAttribLocation(mProgram, "a_Position");
GLES20.glVertexAttrib3f(pointPositionHandle, lightLocation[0], lightLocation[1], lightLocation[2]);
GLES20.glUniformMatrix4fv(pointMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
GLES20.glDisableVertexAttribArray(pointPositionHandle);
}}
我的模型代码:
public class Test {
final String vertexShaderCode =
"uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix.
+ "uniform mat4 u_MVMatrix; \n" // A constant representing the combined model/view matrix.
+ "uniform vec3 u_LightPos; \n" // The position of the light in eye space.
+ "attribute vec4 a_Position; \n" // Per-vertex position information we will pass in.
+ "attribute vec4 a_Color; \n" // Per-vertex color information we will pass in.
+ "attribute vec3 a_Normal; \n" // Per-vertex normal information we will pass in.
+ "varying vec4 v_Color; \n" // This will be passed into the fragment shader.
+ "void main() \n" // The entry point for our vertex shader.
+ "{ \n"
// Transform the vertex into eye space.
+ " vec3 modelViewVertex = vec3(u_MVMatrix * a_Position); \n"
// Transform the normal's orientation into eye space.
+ " vec3 modelViewNormal = vec3(u_MVMatrix * vec4(a_Normal, 0.0)); \n"
// Will be used for attenuation.
+ " float distance = length(u_LightPos - modelViewVertex); \n"
// Get a lighting direction vector from the light to the vertex.
+ " vec3 lightVector = normalize(u_LightPos - modelViewVertex); \n"
// Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
// pointing in the same direction then it will get max illumination.
+ " float diffuse = max(dot(modelViewNormal, lightVector), 0.1); \n"
// Attenuate the light based on distance.
+ " diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance))); \n"
// Multiply the color by the illumination level. It will be interpolated across the triangle.
+ " v_Color = a_Color * diffuse; \n"
// 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; \n"
+ "} \n";
private final String fragmentShaderCode =
"precision mediump float; \n" // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
+ "varying vec4 v_Color; \n" // This is the color from the vertex shader interpolated across the
// triangle per fragment.
+ "void main() \n" // The entry point for our fragment shader.
+ "{ \n"
+ " gl_FragColor = v_Color; \n" // Pass the color directly through the pipeline.
+ "} \n";
private FloatBuffer vertexBuffer;
private FloatBuffer colorBuffer;
private FloatBuffer normalBuffer;
private final int mProgram;
private int mPositionHandle;
private int mNormalHandle;
private int mLightLocationHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
private int mMVMatrixHandle;
final int COORDS_PER_VERTEX = 3;
float[] squareCoords;
float[] coordsNormals;
float color[];
public Test() {
squareCoords = GlassUI10.ReadStlBinary("test.stl");
coordsNormals = VectorCalculate.getNormByPtArray(squareCoords);
color = new float[squareCoords.length/3*4];
for(int i = 0; i < color.length/4 ; i = i+4)
{
color[i+0] =0.3f;
color[i+1] =0.7f;
color[i+2] =0.6f;
color[i+3] =1.3f;
}
System.gc();
Log.v("TestLoaded: ", "Loaded");
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
colorBuffer = ByteBuffer.allocateDirect(color.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
colorBuffer.put(color).position(0);
ByteBuffer nb = ByteBuffer.allocateDirect(coordsNormals.length * 4);
nb.order(ByteOrder.nativeOrder());
normalBuffer = nb.asFloatBuffer();
normalBuffer.put(coordsNormals);
normalBuffer.position(0);
// initialize byte buffer for the draw list
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);//*********ok
int fragmentShader = MyGLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);//*********ok
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glBindAttribLocation(mProgram, 0, "a_Position");
GLES20.glBindAttribLocation(mProgram, 1, "a_Color");
GLES20.glBindAttribLocation(mProgram, 2, "a_Normal");
GLES20.glLinkProgram(mProgram);
}
public void draw(float[] mvpMatrix, float[] mvMatrix) {
GLES20.glUseProgram(mProgram);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");
mMVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVMatrix");
mLightLocationHandle = GLES20.glGetUniformLocation(mProgram, "u_LightPos");
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "a_Position");
mColorHandle = GLES20.glGetUniformLocation(mProgram, "a_Color");
mNormalHandle = GLES20.glGetAttribLocation(mProgram, "a_Normal");
vertexBuffer.position(0);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
colorBuffer.position(0);
GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false, 0, colorBuffer);
GLES20.glEnableVertexAttribArray(mColorHandle);
normalBuffer.position(0);
GLES20.glVertexAttribPointer(mNormalHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, normalBuffer);
GLES20.glEnableVertexAttribArray(mNormalHandle);
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mvMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glUniform3f(mLightLocationHandle, MyGLRenderer.mLightPosInEyeSpace[0], MyGLRenderer.mLightPosInEyeSpace[1], MyGLRenderer.mLightPosInEyeSpace[2]);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, squareCoords.length/COORDS_PER_VERTEX); GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}}
任何答案将不胜感激!
在您的代码中,COORDS_PER_VERTEX
是 3。但是在您的着色器代码中 "attribute vec4 a_Position; \n"
,a_Position 是 vec4。
因此 GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, vertexBuffer);
具有不兼容的矢量大小。
我解决了这个问题。
首先。给定颜色的循环是错误的。修正如下:
for(int i = 0; i < color.length ; i = i+4)
它只导致很少的表面被着色;但这并不是导致模型变黑的主要原因;
主要是漫射光公式中的distance
太大了;它导致 diffuse
变成一个非常小的值,导致颜色 RGB 非常接近于零;
" diffuse = diffuse * (1.0 / (1.0 + (0.00000025 * distance * distance)));"
它需要一个更好的公式,但简单地减少距离值应该显示颜色和光线影响。
这个问题困扰了我一个星期左右... 我试图加载 stl 文件并将其显示在屏幕上。文件已正确读取。不添加光的渲染非常好。添加光照和着色器代码后,模型还在,但变黑了。
我按照本文下面从 link 下载的示例进行操作: http://www.learnopengles.com/android-lesson-two-ambient-and-diffuse-lighting/
着色器代码与示例完全相同。程序 link 没问题。着色器编译也很好。我找不到问题出在哪里。 PLZ帮帮我。
我的渲染器:
public class MyGLRenderer implements GLSurfaceView.Renderer {
private Test test;
private Light1 light1;
private float range = 145;
private final float[] mMVMMatrix = new float[16];
private final float[] mMVPMatrix = new float[16];
private final float[] mModelMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
protected final static float[] mLightPosInEyeSpace = new float[4];
private final float[] mLightModelMatrix = new float[16];
private final float[] mLightPosInModelSpace = new float[] {0.0f, 0.0f, 0.0f, 1.0f};
private final float[] mLightPosInWorldSpace = new float[4];
private final float[] mTempMatrix = new float[16];
public static final float[] mAccumulatedMatrix = new float[16];
private final float[] mCurrMatrix = new float[16];
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthFunc(GLES20.GL_LEQUAL);
Matrix.setIdentityM(mTempMatrix, 0);
Matrix.setIdentityM(mAccumulatedMatrix, 0);
light1 = new Light1();
test = new Test();
}
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setIdentityM(mViewMatrix, 0);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.setIdentityM(mCurrMatrix, 0);
Matrix.setIdentityM(mLightModelMatrix, 0);
Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0, mLightPosInModelSpace, 0);
Matrix.multiplyMV(mLightPosInEyeSpace, 0, mViewMatrix, 0, mLightPosInWorldSpace, 0);
Matrix.rotateM(mCurrMatrix, 0, mAngleY, 0.0f, 1.0f, 0.0f);
Matrix.rotateM(mCurrMatrix, 0, mAngleX, 1.0f, 0, 0.0f);
mAngleX = 0.0f;
mAngleY = 0.0f;
Matrix.multiplyMM(mTempMatrix, 0, mCurrMatrix, 0, mAccumulatedMatrix, 0);
System.arraycopy(mTempMatrix, 0, mAccumulatedMatrix, 0, 16);
Matrix.multiplyMM(mTempMatrix, 0, mModelMatrix, 0, mAccumulatedMatrix, 0);
System.arraycopy(mTempMatrix, 0, mModelMatrix, 0, 16);
Matrix.translateM(mModelMatrix, 0, -test.meanX, -test.meanY, -test.meanZ);
Matrix.multiplyMM(mMVMMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVMMatrix, 0);
light1.draw(mMVPMatrix);
test.draw(mMVPMatrix, mMVMMatrix);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.orthoM(mProjectionMatrix, 0, -range*ratio, range*ratio, -range, range, -range, range);
}
public final static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public static volatile float mAngleX;
public static volatile float mAngleY;
public static void setAngleX(float angle) {mAngleX = angle;}
public float getAngleX() {
return mAngleX;
}
public static void setAngleY(float angle) {
mAngleY = angle;
}
public float getAngleY() {
return mAngleY;
}}
我用来绘制光线位置的代码:
public class Light1 {
private final String vertexShaderCode =
"uniform mat4 u_MVPMatrix; \n"
+ "attribute vec4 a_Position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_MVPMatrix \n"
+ " * a_Position; \n"
+ " gl_PointSize = 5.0; \n"
+ "} \n";
private final String fragmentShaderCode =
"precision mediump float; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4(1.0, \n"
+ " 1.0, 1.0, 1.0); \n"
+ "} \n";
//Light*******************
public static float[] lightLocation = new float[] {150, 150, 0};//*********ok
private final int mProgram;
//Light*******************
public Light1() {
// initialize byte buffer for the draw list
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
}
public void draw(float[] mvpMatrix) {
GLES20.glUseProgram(mProgram);
final int pointMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");
final int pointPositionHandle = GLES20.glGetAttribLocation(mProgram, "a_Position");
GLES20.glVertexAttrib3f(pointPositionHandle, lightLocation[0], lightLocation[1], lightLocation[2]);
GLES20.glUniformMatrix4fv(pointMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
GLES20.glDisableVertexAttribArray(pointPositionHandle);
}}
我的模型代码:
public class Test {
final String vertexShaderCode =
"uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix.
+ "uniform mat4 u_MVMatrix; \n" // A constant representing the combined model/view matrix.
+ "uniform vec3 u_LightPos; \n" // The position of the light in eye space.
+ "attribute vec4 a_Position; \n" // Per-vertex position information we will pass in.
+ "attribute vec4 a_Color; \n" // Per-vertex color information we will pass in.
+ "attribute vec3 a_Normal; \n" // Per-vertex normal information we will pass in.
+ "varying vec4 v_Color; \n" // This will be passed into the fragment shader.
+ "void main() \n" // The entry point for our vertex shader.
+ "{ \n"
// Transform the vertex into eye space.
+ " vec3 modelViewVertex = vec3(u_MVMatrix * a_Position); \n"
// Transform the normal's orientation into eye space.
+ " vec3 modelViewNormal = vec3(u_MVMatrix * vec4(a_Normal, 0.0)); \n"
// Will be used for attenuation.
+ " float distance = length(u_LightPos - modelViewVertex); \n"
// Get a lighting direction vector from the light to the vertex.
+ " vec3 lightVector = normalize(u_LightPos - modelViewVertex); \n"
// Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
// pointing in the same direction then it will get max illumination.
+ " float diffuse = max(dot(modelViewNormal, lightVector), 0.1); \n"
// Attenuate the light based on distance.
+ " diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance))); \n"
// Multiply the color by the illumination level. It will be interpolated across the triangle.
+ " v_Color = a_Color * diffuse; \n"
// 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; \n"
+ "} \n";
private final String fragmentShaderCode =
"precision mediump float; \n" // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
+ "varying vec4 v_Color; \n" // This is the color from the vertex shader interpolated across the
// triangle per fragment.
+ "void main() \n" // The entry point for our fragment shader.
+ "{ \n"
+ " gl_FragColor = v_Color; \n" // Pass the color directly through the pipeline.
+ "} \n";
private FloatBuffer vertexBuffer;
private FloatBuffer colorBuffer;
private FloatBuffer normalBuffer;
private final int mProgram;
private int mPositionHandle;
private int mNormalHandle;
private int mLightLocationHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
private int mMVMatrixHandle;
final int COORDS_PER_VERTEX = 3;
float[] squareCoords;
float[] coordsNormals;
float color[];
public Test() {
squareCoords = GlassUI10.ReadStlBinary("test.stl");
coordsNormals = VectorCalculate.getNormByPtArray(squareCoords);
color = new float[squareCoords.length/3*4];
for(int i = 0; i < color.length/4 ; i = i+4)
{
color[i+0] =0.3f;
color[i+1] =0.7f;
color[i+2] =0.6f;
color[i+3] =1.3f;
}
System.gc();
Log.v("TestLoaded: ", "Loaded");
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
colorBuffer = ByteBuffer.allocateDirect(color.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
colorBuffer.put(color).position(0);
ByteBuffer nb = ByteBuffer.allocateDirect(coordsNormals.length * 4);
nb.order(ByteOrder.nativeOrder());
normalBuffer = nb.asFloatBuffer();
normalBuffer.put(coordsNormals);
normalBuffer.position(0);
// initialize byte buffer for the draw list
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);//*********ok
int fragmentShader = MyGLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);//*********ok
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glBindAttribLocation(mProgram, 0, "a_Position");
GLES20.glBindAttribLocation(mProgram, 1, "a_Color");
GLES20.glBindAttribLocation(mProgram, 2, "a_Normal");
GLES20.glLinkProgram(mProgram);
}
public void draw(float[] mvpMatrix, float[] mvMatrix) {
GLES20.glUseProgram(mProgram);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");
mMVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVMatrix");
mLightLocationHandle = GLES20.glGetUniformLocation(mProgram, "u_LightPos");
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "a_Position");
mColorHandle = GLES20.glGetUniformLocation(mProgram, "a_Color");
mNormalHandle = GLES20.glGetAttribLocation(mProgram, "a_Normal");
vertexBuffer.position(0);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
colorBuffer.position(0);
GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false, 0, colorBuffer);
GLES20.glEnableVertexAttribArray(mColorHandle);
normalBuffer.position(0);
GLES20.glVertexAttribPointer(mNormalHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, normalBuffer);
GLES20.glEnableVertexAttribArray(mNormalHandle);
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mvMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glUniform3f(mLightLocationHandle, MyGLRenderer.mLightPosInEyeSpace[0], MyGLRenderer.mLightPosInEyeSpace[1], MyGLRenderer.mLightPosInEyeSpace[2]);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, squareCoords.length/COORDS_PER_VERTEX); GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}}
任何答案将不胜感激!
在您的代码中,COORDS_PER_VERTEX
是 3。但是在您的着色器代码中 "attribute vec4 a_Position; \n"
,a_Position 是 vec4。
因此 GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, vertexBuffer);
具有不兼容的矢量大小。
我解决了这个问题。
首先。给定颜色的循环是错误的。修正如下:
for(int i = 0; i < color.length ; i = i+4)
它只导致很少的表面被着色;但这并不是导致模型变黑的主要原因;
主要是漫射光公式中的distance
太大了;它导致 diffuse
变成一个非常小的值,导致颜色 RGB 非常接近于零;
" diffuse = diffuse * (1.0 / (1.0 + (0.00000025 * distance * distance)));"
它需要一个更好的公式,但简单地减少距离值应该显示颜色和光线影响。