I am starting with this as a basis.
https://github.com/danginsburg/opengles-book-samples/tree/master/Android/Ch13_ParticleSystem
So I have been reading the book that this is based off of and I am struggling to understand how to load another object into the buffer that is not a bitmap. For instance i have created a cube class with normals, vertices, and textures
class Cube
{
public final float VERTICES[] = {
-0.5f, -0.5f, -0.5f, // Back bottom left
0.5f, -0.5f, -0.5f, // Back bottom right
0.5f, 0.5f, -0.5f, // Back top right
-0.5f, 0.5f, -0.5f, // Back top left
-0.5f, -0.5f, 0.5f, // Front bottom left
0.5f, -0.5f, 0.5f, // Front bottom right
0.5f, 0.5f, 0.5f, // Front top right
-0.5f, 0.5f, 0.5f // Front top left
};
final float[] cubeNormalData =
{
// Front face
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
// Right face
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
// Back face
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
// Left face
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
// Top face
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
// Bottom face
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f
};
final float[] cubeTextureCoordinateData =
{
// Front face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Right face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Back face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Left face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Top face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Bottom face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
}
I'm assuming I will need to write a new function to load the cube data, may need help fleshing this out.
private int loadCube() {
Cube cube = new Cube();
float [] cubeData;
float[] cubeVerts = cube.getVERTICES();
float[] cubeNorms = cube.getCubeNormalData();
float[] cubeTexts = cube.getCubeTextureCoordinateData();
for (int i=0; i<NUM_PARTICLES;i++)
{
// add all the parts to the buffer somehow
}
//do some kind og GLES20.glBind
return particleId[0]; // im not sure what this index does just yet but loadTexture has one
}
I think that's what I have to do, though if i missed some important please let me know.
EDIT**********************************************
OK so, I've been making progress and realized that my question was probably too vague. I am currently getting an index out of bounds error, though im sure i am binding the data incorrectly and doing something wrong with the shader. If you could point out what i am doing wrong that would be greatly appreciated
I am loading the data into one buffer of size 32 where:
//[0] is lifetime
//1-3 is end pos
//4-6 is start post
//7-31 is vert data which is added from the cube
So i have these member variables
private FloatBuffer mParticles;
private Context mContext;
private final int NUM_PARTICLES = 10000;
private final int PARTICLE_SIZE = 32; // was 7
private final float[] mParticleData = new float[NUM_PARTICLES * PARTICLE_SIZE];
then i have an onSurfaceCreate Function which i am getting an out of bounds error for when i try to add the verts
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
String vShaderStr =
"uniform float u_time; \n" +
"uniform vec3 u_centerPosition; \n" +
"attribute float a_lifetime; \n" +
"attribute vec3 a_startPosition; \n" +
"attribute vec3 a_endPosition; \n" +
"varying float v_lifetime; \n" +
"void main() \n" +
"{ \n" +
" if ( u_time <= a_lifetime ) \n" +
" { \n" +
" vec3 rotation = vec3(.1*cos(u_time*10),0,.1*cos(u_time*10)); \n" +
" gl_Position.xyz = a_startPosition + rotation + \n" +
" (u_time/10f * a_endPosition); \n" +
" gl_Position.xyz += u_centerPosition; \n" +
" gl_Position.w = 1.0; \n" +
" } \n" +
" else \n" +
" gl_Position = vec4( -1000, -1000, -1000, 0 ); \n" +
" v_lifetime = 1.0 - ( u_time / a_lifetime ); \n" +
" v_lifetime = clamp ( v_lifetime, 0.0, 1.0 ); \n" +
" gl_PointSize = 40.0; \n" +
"}";
String fShaderStr =
"precision mediump float; \n" +
"uniform vec4 u_color; \n" +
"varying float v_lifetime; \n" +
"uniform sampler2D s_texture; \n" +
"void main() \n" +
"{ \n" +
" vec4 texColor; \n" +
" texColor = texture2D( s_texture, gl_PointCoord ); \n" +
" gl_FragColor = vec4( u_color ) * texColor; \n" +
" gl_FragColor.a *= v_lifetime; \n" +
"} \n";
// Load the shaders and get a linked program object
mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
// Get the attribute locations
mLifetimeLoc = GLES20.glGetAttribLocation(mProgramObject, "a_lifetime");
mStartPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_startPosition");
mEndPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_endPosition");
mVertStartPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_vertStartPosition");
// Get the uniform locations
mTimeLoc = GLES20.glGetUniformLocation(mProgramObject, "u_time");
mCenterPositionLoc = GLES20.glGetUniformLocation(mProgramObject, "u_centerPosition");
mColorLoc = GLES20.glGetUniformLocation(mProgramObject, "u_color");
mSamplerLoc = GLES20.glGetUniformLocation(mProgramObject, "s_texture");
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Cube cube = new Cube();
float[] cubeVerts = cube.getVERTICES();
// Fill in particle data array
Random generator = new Random();
for (int i = 0; i < NUM_PARTICLES; i++) { //num particles =31
//[0] is lifetime
//1-3 is end pos
//4-6 is start post
//7-31 is vert data which is added from the cube
// Lifetime of particle
mParticleData[i * PARTICLE_SIZE + 0] = generator.nextFloat() *10f;
// End position of particle
mParticleData[i * PARTICLE_SIZE + 1] = generator.nextFloat() * 2.0f - 1.0f;
mParticleData[i * PARTICLE_SIZE + 2] = generator.nextFloat() * 5.0f +5f;// - 1.0f;
mParticleData[i * PARTICLE_SIZE + 3] = generator.nextFloat() * 2.0f - 1.0f;
// Start position of particle
mParticleData[i * PARTICLE_SIZE + 4] = generator.nextFloat() * 0.25f - 0.125f;
mParticleData[i * PARTICLE_SIZE + 5] = generator.nextFloat() * 0.25f - 0.125f;
mParticleData[i * PARTICLE_SIZE + 6] = generator.nextFloat() * 0.25f - 0.125f;
for(int x=0; x<cubeVerts.length;x++)
{
mParticleData[i *PARTICLE_SIZE + 7 + x] = cubeVerts[x];
}
}
mParticles = ByteBuffer.allocateDirect(mParticleData.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mParticles.put(mParticleData).position(0);
// Initialize time to cause reset on first update
mTime = 10f;
}
And in my onDrawFrame i have this:
public void onDrawFrame(GL10 glUnused) {
update();
// Set the viewport
GLES20.glViewport(0, 0, mWidth, mHeight);
// Clear the color buffer
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Use the program object
GLES20.glUseProgram(mProgramObject);
// Load the vertex attributes
mParticles.position(0);
GLES20.glVertexAttribPointer(mLifetimeLoc, 1, GLES20.GL_FLOAT,
false, PARTICLE_SIZE * 4,
mParticles);
mParticles.position(1);
GLES20.glVertexAttribPointer(mEndPositionLoc, 3, GLES20.GL_FLOAT,
false, PARTICLE_SIZE * 4,
mParticles);
mParticles.position(4);
GLES20.glVertexAttribPointer(mStartPositionLoc, 3, GLES20.GL_FLOAT,
false, PARTICLE_SIZE * 4,
mParticles);
mParticles.position(7);
GLES20.glVertexAttribPointer(mVertStartPositionLoc, 4, GLES20.GL_FLOAT,
false, PARTICLE_SIZE * 4,
mParticles);
GLES20.glEnableVertexAttribArray(mLifetimeLoc);
GLES20.glEnableVertexAttribArray(mEndPositionLoc);
GLES20.glEnableVertexAttribArray(mStartPositionLoc);
GLES20.glEnableVertexAttribArray(mVertStartPositionLoc);
// Blend particles
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE);
// Set the sampler texture unit to 0
GLES20.glUniform1i(mSamplerLoc, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
//GLES20.glDrawArrays(GLES20.GL_POINTS, 0, NUM_PARTICLES);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,NUM_PARTICLES*36);
}
Related
i just spend my whole day trying to figur out, how to get diffuse lighting in opengl to run. for some reason, my model aka a simple cube just stays completely black, when i use the diffuse Shader. this is the VertexShader(just ignore the lines until gl_Position, those are for my own projektion algotythm and the only important things in here are the v_Position the v_Normal, which are basicly just the position and the normal after all the transforms like for example rotation):
#version 300 es
in vec3 aPos;
in vec3 normal;
uniform vec4 vm;
uniform vec4 aColor;
out vec3 v_Position;
out vec4 v_Color;
out vec3 v_Normal;
void main()
{
vec3 lightPos = vec3(2.0f, 2.0f, 3.0f);
float x2 = (aPos.x * cos(vm.y) - (aPos.z) * sin(vm.y));
float z2 = ((aPos.x * sin(vm.y) + (aPos.z) * cos(vm.y))) + 7.0f;
float y2 = (aPos.y * cos(vm.z) - (z2 - 7.0f) * sin(vm.z));
float z3 = ((aPos.y * sin(vm.z) + (z2 - 7.0f) * cos(vm.z))) + 7.0f;
float nx2 = (normal.x * cos(vm.y) - (normal.z) * sin(vm.y));
float nz2 = ((normal.x * sin(vm.y) + (normal.z) * cos(vm.y))) + 7.0f;
float ny2 = (normal.y * cos(vm.z) - (nz2 - 7.0f) * sin(vm.z));
float nz3 = ((normal.y * sin(vm.z) + (nz2 - 7.0f) * cos(vm.z))) + 7.0f;
float dst = sqrt((x2 * x2) + (y2 * y2) + (z3 * z3));
gl_Position = vec4(x2 / z3 * vm.x,y2 / z3 * vm.x * vm.w, dst * 0.0001,1.0f);
v_Position = vec3(x2, y2, z3);
v_Color = aColor;
v_Normal = vec3(nx2, ny2, nz3);
}
this is the FragmentShader :
#version 300 es
precision mediump float;
uniform vec3 u_LightPos;
in vec3 v_Position;
in vec4 v_Color;
in vec3 v_Normal;
out vec4 FragColor;
void main()
{
float distance = length(vec3(u_LightPos) - v_Position);
vec3 lightVector = normalize(vec3(u_LightPos) - v_Position);
float diffuse = max(dot(v_Normal, lightVector), 0.1);
diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance)));
FragColor = vec4(vec3(v_Color) * (diffuse), 1.0f);
}
for u_LightPos i passed in 0.0f, 0.0f, 0.0f, 0.0f
for aColor : 1.0f, 0.0f, 0.0f, 1.0f
in case it helps, this is my vertexBuffer(the stride is 6 and the first three floats are for position the next three for the normals) :
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f
I have no idea why, but i yeeted out everything which had something to do with u_LightPos and now it works
I've recently started using OpenGL ES 2 for android. I followed their examples for drawing shapes, and I went further and created a cube. I'm now trying to achieve a nice color effect(each face a different color). I ve defined a colorBuffer which has a color for each vertex, but when I'm drawing the shape the image is black.
If I use only one color, instead of the buffer the shape is fine.
I tried to adapt my colorBuffer from the positionBuffer, but I'm doing something wrong.
Here is my code:
public class Cube {
private FloatBuffer vertexBuffer; // Buffer for vertex-array
private final FloatBuffer colorsBuffer;
private static final int COORDS_PER_VERTEX = 3;
private static final int COORDS_PER_COLOR = 4;
private ShortBuffer drawListBuffer;
private int mColorHandle;
// float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
private float colors[] ={
// FRONT
1.0f, 0.5f, 0.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f,
//RIGHT
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
//RIGHT
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
//RIGHT
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
//RIGHT
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
//RIGHT
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
};
short[] drawOrder = {
0, 1, 2, 0, 2, 3,
4, 5, 6, 4, 6, 7,
8, 9, 10, 8, 10, 11,
12, 13, 14, 12, 14, 15,
16, 17, 18, 16, 18, 19,
20, 21, 22, 20, 22, 23,
};
private float cubeCoords[] = {
// FRONT
-1.0f, 1.0f, 1.0f, // 0. top-left-front
-1.0f, -1.0f, 1.0f, // 1. bottom-left-front
1.0f, -1.0f, 1.0f, // 2. bottom-right-front
1.0f, 1.0f, 1.0f, // 3. top-right-front
// RIGHT
1.0f, 1.0f, 1.0f, // 3. top-right-front
1.0f, -1.0f, 1.0f, // 2. bottom-right-front
1.0f, -1.0f, -1.0f, // 4. right-top-front
1.0f, 1.0f, -1.0f, // 5. right-top-back
// BACK
1.0f, 1.0f, -1.0f, // 5. right-top-back
1.0f, -1.0f, -1.0f, // 4. right-top-front
-1.0f, -1.0f, -1.0f, // 6. right-top-back
-1.0f, 1.0f, -1.0f, // 7. left-top-back
// LEFT
-1.0f, 1.0f, -1.0f, // 7. left-top-back
-1.0f, -1.0f, -1.0f, // 6. right-top-back
-1.0f, -1.0f, 1.0f, // 1. bottom-left-front
-1.0f, 1.0f, 1.0f, // 0. top-left-front
// BOTTOM
-1.0f, -1.0f, 1.0f, // 1. bottom-left-front
1.0f, -1.0f, 1.0f, // 2. bottom-right-front
1.0f, -1.0f, -1.0f, // 4. right-top-front
-1.0f, -1.0f, -1.0f, // 6. right-top-back
// TOP
-1.0f, 1.0f, 1.0f, // 0. top-left-front
1.0f, 1.0f, 1.0f, // 3. top-right-front
1.0f, 1.0f, -1.0f, // 5. right-top-back
-1.0f, 1.0f, -1.0f, // 7. left-top-back
};
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private int MVPMatrixHandle;
private int mPositionHandle;
private int colorHandle;
private final int mProgram;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
private final int colorStride = COORDS_PER_COLOR * 4;
private final int vertexCount = cubeCoords.length / COORDS_PER_VERTEX;
// Constructor - Set up the buffers
public Cube() {
Log.d("TAG","vertexCount: "+vertexCount);
// Setup vertex-array buffer. Vertices in float. An float has 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(cubeCoords.length * 4);
vbb.order(ByteOrder.nativeOrder()); // Use native byte order
vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float
vertexBuffer.put(cubeCoords); // Copy data into buffer
vertexBuffer.position(0); // Rewind
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
colorsBuffer = ByteBuffer.allocateDirect(colors.length * 4).order(ByteOrder.nativeOrder())
.asFloatBuffer();
colorsBuffer.put(colors);
colorsBuffer.position(0);
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);
}
// Draw the shape
public void draw(float[] mvpMatrix) {
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
MVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
// GLES20.glUniform4fv(mColorHandle, 1, color, 0);
GLES20.glEnableVertexAttribArray(mColorHandle);
GLES20.glVertexAttribPointer(mColorHandle, COORDS_PER_COLOR, GLES20.GL_FLOAT, false,
colorStride, colorsBuffer);
GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
You're not doing anything with the color data in your shader programs, so you're uploading the data and not doing anything with it.
You need to add handling code for the new vertex attribute to your shaders; something like this:
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"attribute mediump vec4 vColor;" +
"varying mediump vec4 vaColor;" +
"void main() {" +
" vaColor = vColor;" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"varying mediump vec4 vaColor;" +
"void main() {" +
" gl_FragColor = vaColor;" +
"}";
I've been reading a lot about textures in Open GL ES 2.0 today. My problem is, that they are all black.
My code:
To generate a texture from a bitmap:
private void generateTexture(Bitmap bmp) {
final int[] textureHandle = new int[1];
Log.d(TAG, "Generating texture handle");
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0) {
Log.d(TAG, "binding texture to " + textureHandle[0]);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
Log.d(TAG, "GLError#bindTex=" + GLES20.glGetError());
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_CLAMP_TO_EDGE);
Log.d(TAG, "Loading bitmap into texture");
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
Log.d(TAG, "GLError#texImg2D=" + GLES20.glGetError());
Log.d(TAG, "Recycle bitmap");
// Recycle the bitmap, since its data has been loaded into OpenGL.
bmp.recycle();
}
There are no errors in my logcat, everything seems to be like it's supposed to.
How I use the texture:
if (mShader instanceof Texture2DShader && mTextureBuffer != null) {
// activate texture
Log.d(TAG, "Passing texture stuff");
mTextureBuffer.position(0);
Log.d(TAG, "Activate Texture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
Log.d(TAG, "Binding texture -> " + mTexture.getHandle());
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexture.getHandle());
if (mShader.getGLLocation(BaseShader.U_TEXTURE) != -1) {
Log.d(TAG, "Passing u_Texture");
GLES20.glUniform1i(mShader.getGLLocation(BaseShader.U_TEXTURE), 0);
}
if (mShader.getGLLocation(BaseShader.A_TEXCOORDINATE) != -1) {
Log.d(TAG, "Passing a_TexCoordinate");
GLES20.glVertexAttribPointer(mShader.getGLLocation(BaseShader.A_TEXCOORDINATE), 2, GLES20.GL_FLOAT, false, 0, mTextureBuffer);
GLES20.glEnableVertexAttribArray(mShader.getGLLocation(BaseShader.A_TEXCOORDINATE));
}
Log.d(TAG, "Texture stuff passed.");
Log.d(TAG, "Error = " + GLES20.glGetError());
}
Logcat says something like this:
D/TextureCube﹕ Activate Texture
D/TextureCube﹕ Binding texture -> 3
D/TextureCube﹕ Passing u_Texture
D/TextureCube﹕ Passing a_TexCoordinate
D/TextureCube﹕ Texture stuff passed.
D/TextureCube﹕ Error = 0
So no error, seems to be working?
My shaders:
Fragment shader:
precision mediump float; // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
uniform vec3 u_LightPos; // The position of the light in eye space.
uniform vec4 u_Light;
uniform vec4 u_Ambient;
uniform vec3 u_LightDirection;
uniform vec3 u_CameraPos;
uniform sampler2D u_Texture;
//varying vec4 v_Ambient; // Ambient light factor!
varying vec2 v_TexCoordinate;
varying vec3 v_Position; // Interpolated position for this fragment.
varying vec4 v_Color; // This is the color from the vertex shader interpolated across the triangle per fragment.
varying vec3 v_Normal; // Interpolated normal for this fragment.
//varying vec3 v_CameraPosition;
// The entry point for our fragment shader.
void main()
{
// Will be used for attenuation.
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);
// 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(v_Normal, lightVector), 0.1);
// Add attenuation. (used to be 0.25)
diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance)));
// calculate specular light!
//vec3 lightDirection = -u_LightDirection;
//vec3 vertexToEye = normalize(u_CameraPos - v_CameraPos);
//vec3 lightReflect = normalize(reflect(u_LightDirection, v_Normal));
//float specularFactor = dot(vertexToEye, lightReflect);
// Multiply the color by the diffuse illumination level to get final output color.
//
gl_FragColor = v_Color * (u_Ambient + (diffuse * u_Light) * texture2D(u_Texture, v_TexCoordinate));
}
Vertex Shader:
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.
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;
varying vec2 v_TexCoordinate;
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 vec3 v_CameraPosition;
//varying vec4 v_Ambient; // Pass the ambient color to 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);
v_TexCoordinate = a_TexCoordinate;
// Pass through the color.
v_Color = a_Color;
// Transform the normal's orientation into eye space.
v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0));
//v_CameraPos = vec3(u_MVMatrix * vec4(u_CameraPos, 0.0));
// v_CameraPosition = u_CameraPos;
// 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;
}
Seems like texture2D returns a zero vector in the fragment shader, since if I simply write gl_FragColor = vec4(0.5,0.5,0.5,1.0) + texture2D(..) it is drawn.
I've already looked at countless questions here on SO as well as other websites, I know this exact question has been asked a couple of times, but no matter what I've tried - it did not help.
I've already downscaled my texture to 512x512, then 256x256, and even lower up to 64x64 but no changes. I've printed out my texture handlers, checked for GL errors, etc. but nothing.
EDIT:
At first I've been trying to load the texture from R.raw, then moved it to R.drawable, but no change.
EDIT 2: Cube vertices/normals/texture/color declaration:
private final float[] mCubePosition = {
// Front face
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
// Right face
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
// Back face
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
// Left face
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
// Top face
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
// Bottom face
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
};
// R, G, B, A
private final float[] mCubeColors =
{
// Front face (red)
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
// Right face (green)
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
// Back face (blue)
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
// Left face (yellow)
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
// Top face (cyan)
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
// Bottom face (magenta)
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f
};
private final float[] mCubeNormals =
{
// Front face
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
// Right face
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
// Back face
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
// Left face
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
// Top face
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
// Bottom face
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f
};
private final float[] mCubeTexture =
{
// Front face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Right face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Back face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Left face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Top face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Bottom face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
EDIT 3: Texture Coordinates as Colors to see if they are being transmitted:
gl_FragColor = vec4(v_TexCoordinate.x, v_TexCoordinate.y, 0, 1); in the fragment shader results in:
this is a very common issue then you do not work with power of 2 textures (pixel wise).
To not repeat here the same already provided solution, please have a look to my previous response on this matter.
Android OpenGL2.0 showing black textures
I hope this will solve your issue.
Cheers
Maurizio
Ok, I found the solution. I was again confused by the way the OpenGL thread works. I was loading the Bitmap in a thread, then using glView.post(); to post a Runnable back to the (what I thought) OpenGL thread, where the texture was supposed to be generated and bound to the bitmap.
This does not work. What I should have done is:
GLSurfaceView glView = ...;
glView.queueEvent(new Runnable() {
#Override
public void run() {
generateTexture(bitmap);
}
});
Where in generateTexture, I execute all the GLES20.generateTexture etc stuff, since with queueEvent, it's again on the real OpenGL thread, not on the UI thread.
Apparently, my code for using the texture has been correct. Thanks for your help.
I'm trying to add per vertex lighting in OpenGL ES and I'm encountering strange problems for which I didn't find solution.
I first used Android documentation to create shapes :
http://developer.android.com/training/graphics/opengl/index.html
Then I used learn opengl es to add lightinh :
http://www.learnopengles.com/android-lesson-two-ambient-and-diffuse-lighting/
So here is the code of my renderer :
#Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
// Enable depth testing
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
float[] coords = new float[]{
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f , 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f , 0.5f, 0.5f
};
short[] drawOrder = new short[]{
0,1,2,
0,2,3,
4,5,6,
4,6,7,
};
float[] normals = new float[]{
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
};
float[] colors = new float[]{
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
};
testSolid = new Solid(coords, drawOrder, colors, normals);
}
public void onDrawFrame(GL10 unused) {
float[] lightPos = new float[]{0.5f, 0.5f, -0.5f, 1.0f};
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -5.0f, 0f, 0f, 0f, 0f, 2.0f, 0.0f);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.multiplyMM(mVMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.setIdentityM(mLightModelMatrix, 0);
Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0, lightPos, 0);
Matrix.multiplyMV(mLightPosInEyeSpace, 0, mVMatrix, 0, mLightPosInWorldSpace, 0);
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 1.0f, 0.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mLightMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
// Combine the rotation matrix with the projection and camera view
Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mLightMatrix, 0);
// Draw shape
testSolid.draw(mVMatrix, mMVPMatrix, mLightPosInEyeSpace);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
Then, my code for the Solid :
First, my program :
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"uniform mat4 uMVMatrix;"+
"uniform vec3 uLightPos;"+
"attribute vec3 aNormal;" +
"attribute vec4 aColor;" +
"attribute vec4 aPosition;" +
"varying vec4 vColor;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
" vec3 modelViewVertex = vec3(uMVMatrix * aPosition);"+
" vec3 modelViewNormal = vec3(uMVMatrix * vec4(aNormal, 0.0));"+
" float distance = length(uLightPos - modelViewVertex);"+
" vec3 lightVector = normalize(uLightPos - modelViewVertex);"+
" float diffuse = max(dot(modelViewNormal, lightVector), 0.1);"+
" diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance)));"+
" vColor = aColor * diffuse;"+
" gl_Position = aPosition * uMVPMatrix;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"varying vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
And my draw function :
public void draw(float[] mvMatrix, float[] mvpMatrix, float[] lightPos) {
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// Positions
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, DATA_PER_VERTEX,
GLES20.GL_FLOAT, false,
0, vertexBuffer);
CubeRenderer.checkGlError(String.format("Positions (%d)", mPositionHandle));
// Colors
mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
GLES20.glEnableVertexAttribArray(mColorHandle);
GLES20.glVertexAttribPointer(mColorHandle, 4,
GLES20.GL_FLOAT, false,
0, colorBuffer);
CubeRenderer.checkGlError(String.format("Colors (%d)", mColorHandle));
// Normals
mNormalHandle = GLES20.glGetAttribLocation(mProgram, "aNormal");
GLES20.glVertexAttribPointer(mNormalHandle, 3,
GLES20.GL_FLOAT, false,
0, normalBuffer);
GLES20.glEnableVertexAttribArray(mNormalHandle);
CubeRenderer.checkGlError(String.format("Normals (%d)", mColorHandle));
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
CubeRenderer.checkGlError("glGetUniformLocation");
mMVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVMatrix");
CubeRenderer.checkGlError("glGetUniformLocation");
mLightPosHandle = GLES20.glGetUniformLocation(mProgram, "uLightPos");
CubeRenderer.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mvMatrix, 0);
GLES20.glUniform3f(mLightPosHandle, lightPos[0], lightPos[1], lightPos[2]);
CubeRenderer.checkGlError("glUniformMatrix4fv");
// Draw the polygon
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
But, when I run it, I have very strange result.
First, light is very dim, and not in good place
Second, I have a rotation with touch event, and if I rotate my shape, the light will also rotate.
May you know where this issue comes from ?
Thank you.
I am new to GLES 2.0. It is really making me nervous because OpenGL ES 1 II just set GL_LIGHTNING1 and then the lighting was set. In GLES 2.0 it is not working. In fact the whole screen is black. So please tell me what should I do with the code below. These are the vertices I am setting:
static float quadrateCoords[] = { // in counterclockwise order:
// front
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
// back
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
// left
-0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
// right
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
// up
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
// bottom
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f
};
static float normal[] = {
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f
};
static float quadrateColors[] = { // in counterclockwise order:
// front
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f
};
And the shader code is:
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;\n" +
"uniform mat4 uMVMatrix;\n" +
"uniform vec3 uLightPos;\n" +
"attribute vec4 aPosition;\n" +
"attribute vec4 aColor;\n" +
"attribute vec4 aNormal;\n" +
"varying vec4 vColor;\n" +
"void main() {\n" +
"vec3 modelViewVertex = vec3(uMVMatrix * a_Position);\n" +
"vec3 modelViewNormal = vec3(uMVMatrix * vec4(aNormal, 0.0));\n" +
"float distance = length(uLightPos - modelViewVertex);\n" +
"vec3 lightVector = normalize(uLightPos - modelViewVertex);\n" +
"float diffuse = max(dot(modelViewNormal,lightVector), 0.1):\n" +
"diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance)));\n" +
"vColor = aColor * diffuse;\n" +
"gl_Position = aPosition * uMVPMatrix;\n" +
"}\n";
private final String fragmentShaderCode =
"precision mediump float;\n" +
"varying vec4 vColor;\n" +
"void main() {\n" +
"gl_FragColor = vColor;\n" +
"}\n";
And last the draw function:
public void draw(float[] mvpMatrix, float[] mVMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's aPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
nNormalHandle = GLES20.glGetAttribLocation(mProgram, "aNormal");
nColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
// Enable a handle to the triangle vertices
// Prepare the triangle coordinate data
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
GLES20.glEnableVertexAttribArray(nNormalHandle);
GLES20.glVertexAttribPointer(nNormalHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer2);
GLES20.glEnableVertexAttribArray(nColorHandle);
GLES20.glVertexAttribPointer(nColorHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer3);
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mvpMatrix, 0);
muMVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVMatrix");
GLES20.glUniformMatrix4fv(muMVMatrixHandle, 1, false, mVMatrix, 0);
muLightPosHandle = GLES20.glGetUniformLocation(mProgram, "uLightPos");
GLES20.glUniform3f(muLightPosHandle, 10.0f, 10.0f, 15.0f);
// Front
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
// Back
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 4, 4);
// Left
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 8, 4);
// Right
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 12, 4);
// Top
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 16, 4);
// Right
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 20, 4);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
Debug like this:
gl_FragColor = vec4(0.5, 0, 0, 0.5) + vColor;
find errors if any, although your shader is correct.
If there are still errors after you have tested for errors (by directly using colors in place of custom values) look at this ADS shader
How to implement shadow in OpenglES 1.x (on iPhone)
And another point to remember, disable culling if you have enabled it
You're attempting a dot product between a projection space vector (newNormal), and a world space vector (lightPos).
To perform dot product both vectors must be in the same coordinate space. Either provide the normals in world space coordinates (modelMatrix * aNormal), or provide the lightPos in projection space (viewProjectionMatrix * lightPos).