Related
I need a little bit help with this code... I've done it following developers.android, but it still isn't work! Problem with displaying. There is only green screen with no any rectangle. Can someone help me? Thanks!:)
public class Paddle
{
private FloatBuffer vertexBuffer;
private ShortBuffer drawListBuffer;
private int mProgram;
public static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
private final String vertexShaderCode =
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
static final int COORDS_PER_VERTEX = 3;
static float squareCoords[] = {
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f };
private short drawOrder[] = { 0, 1, 2, 0, 2, 3 };
private float color[] = {1, 1, 1, 1};
private int mPositionHandle;
private int mColorHandle;
private final int vertexCount = squareCoords.length / COORDS_PER_VERTEX;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
public Paddle()
{
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
ByteBuffer dlb = ByteBuffer.allocate(drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
}
public void draw()
{
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
GLES20.glUniform4fv(mColorHandle, 4, color, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
This problem bothers me for about a week...
I tried to load stl files and show it on the screen. The file was read properly. Rendering without adding light was pretty good. After I add lighting and shader codes, the model is still there but turns out black.
I followed the example downloaded from link below this article:
http://www.learnopengles.com/android-lesson-two-ambient-and-diffuse-lighting/
The shader code was completely as the same as the example. The program links fine. The Shaders compile fine, too. I can't find out where the problem is. PLZ help me.
My Renderer:
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;
}}
My code to draw where the light is:
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);
}}
My Model Code:
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);
}}
Any answer will be appreciated!
I fixed the problem.
First. The color-given loop was wrong. Be fixed below:
for(int i = 0; i < color.length ; i = i+4)
It caused only few surface being colored; But this was not the main point to cause the model being black;
The main point is that the distance in diffuse light formula is to big; It cause the diffuse to become a very small value which cause the color RGB goes extremely close to zero;
" diffuse = diffuse * (1.0 / (1.0 + (0.00000025 * distance * distance)));"
It need a better formula, but simply decrease the value of distance should show the color and light affect.
In your code, the COORDS_PER_VERTEX is 3. But in your shader code "attribute vec4 a_Position; \n", the a_Position is vec4.
So GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, vertexBuffer); has incompatible vector size.
I would like to rotate my triangles in Z axis, but I would to do it around the center of the triangle, not the center of the screen. I have researched a lot on that but didn't find any resolution.
Any idea of what could I try to solve it?
public class RendererClass implements Renderer {
FloatBuffer bufferObj1;
FloatBuffer bufferObj2;
int programObj1;
int programObj2;
int positionObj1;
int positionObj2;
int rotationMatrixLocationObj1;
int rotationMatrixLocationObj2;
int colorObj1;
int colorObj2;
float[] rotationMatrixObj1 = new float[16];
float[] rotationMatrixObj2 = new float[16];
#Override
public void onSurfaceCreated(GL10 arg0, EGLConfig config) {
GLES20.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
float[] vertexObj1 = {
-0.8f, 0.8f,
-0.8f, 0.0f,
0.0f, 0.0f
};
float[] vertexObj2 = {
0.8f, 0.8f,
0.8f, 0.0f,
0.0f, 0.0f
};
bufferObj1 = ByteBuffer.allocateDirect(vertexObj1.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexObj1);
bufferObj2 = ByteBuffer.allocateDirect(vertexObj2.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexObj2);
String vssObj1 = "attribute vec4 positionObj1;" +
"uniform mat4 rotationMatrixObj1;" +
"void main(){" +
"gl_Position = rotationMatrixObj1 * positionObj1;" +
"}";
String vssObj2 = "attribute vec4 positionObj2;" +
"uniform mat4 rotationMatrixObj2;" +
"void main(){" +
"gl_Position = rotationMatrixObj2 * positionObj2;" +
"}";
String fssObj1 = "precision mediump float;" +
"uniform vec4 colorObj1;" +
"void main(){" +
"gl_FragColor = colorObj1;" +
"}";
String fssObj2 = "precision mediump float;" +
"uniform vec4 colorObj2;" +
"void main(){" +
"gl_FragColor = colorObj2;" +
"}";
int vsObj1 = glCreateShader(GL_VERTEX_SHADER);
int vsObj2 = glCreateShader(GL_VERTEX_SHADER);
int fsObj1 = glCreateShader(GL_FRAGMENT_SHADER);
int fsObj2 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vsObj1, vssObj1);
glShaderSource(vsObj2, vssObj2);
glShaderSource(fsObj1, fssObj1);
glShaderSource(fsObj2, fssObj2);
glCompileShader(vsObj1);
glCompileShader(vsObj2);
glCompileShader(fsObj1);
glCompileShader(fsObj2);
programObj1 = glCreateProgram();
programObj2 = glCreateProgram();
glAttachShader(programObj1, vsObj1);
glAttachShader(programObj2, vsObj2);
glAttachShader(programObj1, fsObj1);
glAttachShader(programObj2, fsObj2);
glLinkProgram(programObj1);
glLinkProgram(programObj2);
positionObj1 = glGetAttribLocation(programObj1, "positionObj1");
positionObj2 = glGetAttribLocation(programObj2, "positionObj2");
rotationMatrixLocationObj1 = glGetUniformLocation(programObj1, "rotationMatrixObj1");
rotationMatrixLocationObj2 = glGetUniformLocation(programObj2, "rotationMatrixObj2");
colorObj1 = glGetUniformLocation(programObj1, "colorObj1");
colorObj2 = glGetUniformLocation(programObj2, "colorObj2");
}
#Override
public void onSurfaceChanged(GL10 arg0, int width, int height) {
Matrix.setIdentityM(rotationMatrixObj1, 0);
Matrix.rotateM(rotationMatrixObj1, 0, MainActivity.angle, 0, 0, 1);
Matrix.setIdentityM(rotationMatrixObj2, 0);
Matrix.rotateM(rotationMatrixObj2, 0, MainActivity.angle, 0, 0, -1);
}
GL10 gl;
#Override
public void onDrawFrame(GL10 glUnused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
onSurfaceChanged(gl, 0, 0);
glUseProgram(programObj1);
bufferObj1.position(0);
glVertexAttribPointer(positionObj1, 2, GL_FLOAT, false, 0, bufferObj1);
glEnableVertexAttribArray(positionObj1);
glUniform4f(colorObj1, 0.0f, 0.0f, 1.0f, 1.0f);
glUniformMatrix4fv(rotationMatrixLocationObj1, 1, false, rotationMatrixObj1, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glUseProgram(programObj2);
bufferObj2.position(0);
glVertexAttribPointer(positionObj2, 2, GL_FLOAT, false, 0, bufferObj2);
glEnableVertexAttribArray(positionObj2);
glUniform4f(colorObj2, 1.0f, 0.0f, 0.0f, 1.0f);
glUniformMatrix4fv(rotationMatrixLocationObj2, 1, false, rotationMatrixObj2, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
}
You use glDrawArrays so you can alter your triangles in your code any way you want. Use simple trigonometry to rotate your vertices independently.
Rotation matrix rotates vertices around center of coordinate system.
If you want to rotate scene around some other point (x0, y0, z0) you have to do this in 3 simple steps:
translate scene in such way that your point will be in center of coord system (by -x0, -y0, -z0)
rotate
translate back (by x0, y0, z0)
Of course 3 steps of transformation are not needed, matrix multiplication can do this work for us.
I'm trying to use the GL_TEXTURE1 texture unit to draw a simple shape. I know how to draw it using the standard GL_TEXTURE0, but when changing it something is not working.
I thought that from my code below, I just had to change the following:
glActiveTexture(GL_TEXTURE1);
glUniform1i(uTextureLocation, 1);
What I'm missing?
Code:
public class RendererClass implements Renderer {
Context context;
FloatBuffer verticesInBuffer;
int aPositionLocation;
int aTextureLocation;
int uTextureLocation;
int program;
public RendererClass(Context context){
this.context = context;
}
#Override
public void onSurfaceCreated(GL10 arg0, EGLConfig config) {
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
float[] vertices = {
-0.5f, 0.5f, 0.5f, 0.5f,
-1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, 0.0f, 0.0f, 0.0f
};
verticesInBuffer = ByteBuffer.allocateDirect(vertices.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertices);
String vss = "attribute vec4 a_Position;" +
"attribute vec2 a_Texture;" +
"varying vec2 v_Texture;" +
"void main(){" +
" v_Texture = a_Texture;" +
" gl_Position = a_Position;" +
"}";
String fss = "precision mediump float;" +
"varying vec2 v_Texture;" +
"uniform sampler2D u_Texture;" +
"void main(){" +
" gl_FragColor = texture2D(u_Texture, v_Texture);" +
"}";
int vs = glCreateShader(GL_VERTEX_SHADER);
int fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vs, vss);
glShaderSource(fs, fss);
glCompileShader(vs);
glCompileShader(fs);
program = glCreateProgram();
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
aPositionLocation = glGetAttribLocation(program, "a_Position");
// ***** Texture stuff starts here </</</</
// Fase 1
glActiveTexture(GL_TEXTURE0);
int[] genTextures = new int[1];
glGenTextures(1, genTextures, 0);
glBindTexture(GL_TEXTURE_2D, genTextures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Fase 2
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bitmap1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.res_for_test_1, options);
// Fase 3
texImage2D(GL_TEXTURE_2D, 0, bitmap1, 0);
glGenerateMipmap(GL_TEXTURE_2D);
// Fase 4
aTextureLocation = glGetAttribLocation(program, "a_Texture");
uTextureLocation = glGetUniformLocation(program, "u_Texture");
glUniform1i(uTextureLocation, 0);
verticesInBuffer.position(2);
glEnableVertexAttribArray(aTextureLocation);
glVertexAttribPointer(aTextureLocation, 2, GL_FLOAT, false, 16, verticesInBuffer);
// ***** Texture stuff ends here </</</</
}
#Override
public void onSurfaceChanged(GL10 arg0, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
#Override
public void onDrawFrame(GL10 glUnused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
glUseProgram(program);
verticesInBuffer.position(0);
glEnableVertexAttribArray(aPositionLocation);
glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, false, 16, verticesInBuffer);
glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
}
}
You need to specify active texture unit and assign a previously loaded texture to it.
For convenience, I've created a helper function which does all of this. It activates given texture unit, assigns texture with given ID to it and puts this value to sampler2D uniform of shader:
protected void setTexture2D(int textureUnit, int textureID, int uniformID) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + textureUnit);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
GLES20.glUniform1i(uniformID, textureUnit);
}
And then call it like this:
setTexture2D(0, textureID, uniformID);
I am trying to learn OpenGLES 2.0 in android in depth. I am trying to draw a Simple Point at the center of screen but somehow , the point is not showing .
public class MyRenderer implements GLSurfaceView.Renderer {
Context context;
private int mProgram;
private final float[] mViewMatrix=new float[16];
private float[] mProjectionMatrix=new float[16];
private final float[] mPointModelMatrix=new float[16];
private final float[] mMVPMatrix=new float[16];
private final float[] mPointPosInModelSpace = new float[] {0.0f, 0.0f, 0.0f, 1.0f};
private final float[] mPointPosInWorldSpace = new float[4];
private final float[] mPointPosInEyeSpace = new float[4];
private int pointMVPMatrixHandle;
private int pointPositionHandle;
public MyRenderer(Context context){
this.context=context;
}
public void onDrawFrame(GL10 arg0) {
// TODO Auto-generated method stub
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Matrix.setIdentityM(mPointModelMatrix, 0);
Matrix.translateM(mPointModelMatrix, 0, 0.0f, 0.0f, -3.0f);
Matrix.multiplyMV(mPointPosInWorldSpace, 0, mPointModelMatrix, 0, mPointPosInModelSpace, 0);
Matrix.multiplyMV(mPointPosInEyeSpace, 0, mViewMatrix, 0, mPointPosInWorldSpace, 0);
GLES20.glUseProgram(mProgram);
drawPoint();
}
private void drawPoint(){
pointMVPMatrixHandle=GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");
pointPositionHandle=GLES20.glGetAttribLocation(mProgram, "a_position");
GLES20.glVertexAttrib3f(pointPositionHandle, mPointPosInEyeSpace[0], mPointPosInEyeSpace[1], mPointPosInEyeSpace[2]);
GLES20.glDisableVertexAttribArray(pointPositionHandle);
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mPointModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(pointMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Draw the point.
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
GLES20.glViewport(0, 0, width, height);
final float ratio=(float)width/height;
Log.d("Ratio is", " "+ratio);
Log.d("Width is"," "+width+" and "+height);
final float left = -ratio;
final float right = ratio;
final float bottom= -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 10.0f;
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
float eyeX=0.0f;
float eyeY=0.0f;
float eyeZ=-0.5f;
float centerX=0.0f;
float centerY=0.0f;
float centerZ=-5.0f;
float upX=0.0f;
float upY=1.0f;
float upZ=0.0f;
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
final String vertexShader=this.getVertexShader();
final String fragmentShader=this.getFragmentShader();
final int vertexShaderHandle=ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);
final int fragmentShaderHandle=ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
mProgram=ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, new String[]{"a_position"});
}
private String getVertexShader(){
final String vertexShader="uniform mat4 u_MVPMatrix; \n"
+ "attribute vec4 a_Position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_MVPMatrix \n"
+ " * a_Position; \n"
+ " gl_PointSize = 10.0; \n"
+ "} \n";
return vertexShader;
}
private String getFragmentShader(){
final String fragmentShader="precision mediump float; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4(1.0, \n"
+ " 1.0, 1.0, 1.0); \n"
+ "} \n";
return fragmentShader;
}
}
I am pretty much sure that I am pointing the both eye and point in negative Z direction(further from viewer) . The point should show up as in vertex Shader, point size is 10.0 but somehow, no luck.
Note: ShaderHelper is a class with static method compileShader and createAndLinkProgram where code for compiling shaders, checking for errors are written. (No Errors in Program)
Here is a class I built based around your code for displaying the point. Since you will probably use more than one point eventually it is better to push the points into a vertex array as shown.
package point.example.point;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
public class PointRenderer implements GLSurfaceView.Renderer
{
private float[] mModelMatrix = new float[16];
private float[] mViewMatrix = new float[16];
private float[] mProjectionMatrix = new float[16];
private float[] mMVPMatrix = new float[16];
private int mMVPMatrixHandle;
private int mPositionHandle;
float[] vertices = {
0.0f,0.0f,0.0f
};
FloatBuffer vertexBuf;
#Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
{
vertexBuf = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuf.put(vertices).position(0);
// Set the background clear color to gray.
GLES20.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
float eyeX=0.0f;
float eyeY=0.0f;
float eyeZ=0.0f;
float centerX=0.0f;
float centerY=0.0f;
float centerZ=-5.0f;
float upX=0.0f;
float upY=1.0f;
float upZ=0.0f;
// Set the view matrix. This matrix can be said to represent the camera position.
// NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
// view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
final String vertexShader =
"uniform mat4 u_MVPMatrix; \n"
+ "attribute vec4 a_Position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_MVPMatrix \n"
+ " * a_Position; \n"
+ " gl_PointSize = 10.0; \n"
+ "} \n";
final String fragmentShader =
"precision mediump float; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4(1.0, \n"
+ " 1.0, 1.0, 1.0); \n"
+ "} \n";
// Load in the vertex shader.
int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
if (vertexShaderHandle != 0)
{
// Pass in the shader source.
GLES20.glShaderSource(vertexShaderHandle, vertexShader);
// Compile the shader.
GLES20.glCompileShader(vertexShaderHandle);
// Get the compilation status.
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// If the compilation failed, delete the shader.
if (compileStatus[0] == 0)
{
GLES20.glDeleteShader(vertexShaderHandle);
vertexShaderHandle = 0;
}
}
if (vertexShaderHandle == 0)
{
throw new RuntimeException("Error creating vertex shader.");
}
// Load in the fragment shader shader.
int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
if (fragmentShaderHandle != 0)
{
// Pass in the shader source.
GLES20.glShaderSource(fragmentShaderHandle, fragmentShader);
// Compile the shader.
GLES20.glCompileShader(fragmentShaderHandle);
// Get the compilation status.
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// If the compilation failed, delete the shader.
if (compileStatus[0] == 0)
{
GLES20.glDeleteShader(fragmentShaderHandle);
fragmentShaderHandle = 0;
}
}
if (fragmentShaderHandle == 0)
{
throw new RuntimeException("Error creating fragment shader.");
}
// Create a program object and store the handle to it.
int programHandle = GLES20.glCreateProgram();
if (programHandle != 0)
{
// Bind the vertex shader to the program.
GLES20.glAttachShader(programHandle, vertexShaderHandle);
// Bind the fragment shader to the program.
GLES20.glAttachShader(programHandle, fragmentShaderHandle);
// Bind attributes
GLES20.glBindAttribLocation(programHandle, 0, "a_Position");
// Link the two shaders together into a program.
GLES20.glLinkProgram(programHandle);
// Get the link status.
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
// If the link failed, delete the program.
if (linkStatus[0] == 0)
{
GLES20.glDeleteProgram(programHandle);
programHandle = 0;
}
}
if (programHandle == 0)
{
throw new RuntimeException("Error creating program.");
}
// Set program handles. These will later be used to pass in values to the program.
mMVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_MVPMatrix");
mPositionHandle = GLES20.glGetAttribLocation(programHandle, "a_Position");
// Tell OpenGL to use this program when rendering.
GLES20.glUseProgram(programHandle);
}
#Override
public void onSurfaceChanged(GL10 glUnused, int width, int height)
{
// Set the OpenGL viewport to the same size as the surface.
GLES20.glViewport(0, 0, width, height);
// Create a new perspective projection matrix. The height will stay the same
// while the width will vary as per aspect ratio.
final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 100.0f;
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}
#Override
public void onDrawFrame(GL10 glUnused)
{
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
Matrix.setIdentityM(mModelMatrix, 0);
//Push to the distance - note this will have no effect on a point size
Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -5.0f);
Matrix.multiplyMV(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMV(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
//Send the vertex
GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuf);
GLES20.glEnableVertexAttribArray(mPositionHandle);
//Draw the point
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
}
}