I use 2D sprite texture applied to a square with transparent or semi-transparent area but I can't see anything through them (except the background) if there are other textures behind. I can see the background image because I use a transparent GLSurfaceView, the background is applied in a ImageView behind the GLSurfaceView.
My problem in an image:
Actually I use this code in the onSurfaceCreated method:
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
this in onDrawFrame method:
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
mObject1.draw(gl);
mObject2.draw(gl);
and this in draw method of mObject1 and mObject2:
gl.glPushMatrix();
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glTranslatef((float) mPosition.getX(), (float) mPosition.getY(), 0f);
float scaleFactor = (float) (2 * mRadius);
gl.glScalef(scaleFactor, scaleFactor, 0);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glColor4f (1f, 1.0f, 1, 1f);
gl.glFrontFace(GL10.GL_CW);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glPopMatrix();
after
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
put
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
Related
I have next problem.
I'm write some android app which uses opengl es 1.0
I'm using GLSurfaceView and custom Renderer. Here are methods of my custom renderer onDrawFrame, onSurfaceChanged, onSurfaceChanged:
#Override
public void onDrawFrame(GL10 gl) {
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// clear Screen and Depth Buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Reset the Modelview Matrix
gl.glLoadIdentity();
// Drawing
gl.glTranslatef(0f, 0f, -3.0f); // move 5 units INTO the screen
// is the same as moving the camera 5 units away
// gl.glScalef(0.5f, 0.5f, 0.5f); // scale the square to 50%
// otherwise it will be too large
square.draw(gl, mScrollable.getIndexA(), mScrollable.getIndexB(), mScrollable.getAlphaValue()); // Draw the triangle
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if(height == 0) { //Prevent A Divide By Zero By
height = 1; //Making Height Equal One
}
gl.glViewport(0, 0, mWidth, mHeight); //Reset The Current Viewport
gl.glMatrixMode(GL10.GL_PROJECTION); //Select The Projection Matrix
gl.glLoadIdentity(); //Reset The Projection Matrix
//Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix
gl.glLoadIdentity(); //Reset The Modelview Matrix
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Load the texture for the square
square.loadGLTexture(gl, this.context);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL10.GL_TEXTURE_2D); //Enable Texture Mapping ( NEW )
gl.glShadeModel(GL10.GL_SMOOTH); //Enable Smooth Shading
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //Black Background
gl.glClearDepthf(1.0f); //Depth Buffer Setup
gl.glEnable(GL10.GL_DEPTH_TEST); //Enables Depth Testing
gl.glDepthFunc(GL10.GL_LEQUAL); //The Type Of Depth Testing To Do
//Really Nice Perspective Calculations
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
}
And my Square class to render textures:
private int[] textures;
private GL10 mGl;
private FloatBuffer vertexBuffer; // buffer holding the vertices
private float vertices[] = {
-1.0f, -1.8f, 0.0f, // V1 - bottom left
-1.0f, 1.3f, 0.0f, // V2 - top left
1.0f, -1.8f, 0.0f, // V3 - bottom right
1.0f, 1.3f, 0.0f // V4 - top right
};
private FloatBuffer textureBuffer; // buffer holding the texture coordinates
private float texture[] = {
// Mapping coordinates for the vertices
0.0f, 1.0f, // top left (V2)
0.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
};
private GlAnimationCache cacheHelper;
public void loadGLTexture(GL10 gl, Context context) {
// loading texture
mGl = gl;
gl.glGenTextures(mImageEntityList.size(), textures, 0);
cacheHelper = new GlAnimationCache(mContext, mImageEntityList, mGlRenderer, mGlSurfaceView);
cacheHelper.initCache(); //it init cache in background thread
}
public void removeTextureAt(int position){
mGl.glDeleteTextures(1, textures, position);
}
public void bindTextureAt(final Bitmap bitmap, int position){
// generate one texture poi, 0);
// ...and bind it to our array
mGl.glBindTexture(GL10.GL_TEXTURE_2D, textures[position]);
mGl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertexBuffer);
mGl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
// create nearest filtered texture
mGl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
mGl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
//Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
// gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
// gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
// Use Android GLUtils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLUtils.getInternalFormat(bitmap), bitmap, GLUtils.getType(bitmap), 0);
bitmap.recycle();
}
private int prevIndex = 0;
/** The draw method for the square with the GL context */
public void draw(GL10 gl, int indexA, int indexB, float alpha) {
// bind the previously generated texture
if(prevIndex != indexA){
cacheHelper.synchronizeCache(indexA);
prevIndex = indexA;
}
// Point to our buffers
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[indexA]);
// Set the face rotation
gl.glFrontFace(GL10.GL_CW);
// Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glColor4f(1, 1, 1, 1f);
// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[indexB]);
// Set the face rotation
gl.glFrontFace(GL10.GL_CW);
// Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glColor4f(1, 1, 1, Math.abs(alpha));
// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
So, the problem is next: On Samsung S5, Alcatel One Touch 4033D and Motorolla Droid Razr textures are rendered fine. But on Samsung Galaxy Nexus I see only 'white box'.
I have tried to change size of texture to power of 2(512 x 512) but it not helpes.
In Square class add function:
public boolean isNPOTSupported(GL10 gl) {
String extensions = gl.glGetString(GL10.GL_EXTENSIONS);
return extensions.indexOf("GL_OES_texture_npot") != -1;
}
And when you Generate textures, add this:
final boolean isNPOTSupported = isNPOTSupported(gl);
if(isNPOTSupported) {
gl.glGenTextures(mImageEntityList.size(), textures, 0);
}else{
for(int i = 0; i < mImageEntityList.size(); i++){
gl.glGenTextures(1, textures, i);
}
}
Instead this:
gl.glGenTextures(mImageEntityList.size(), textures, 0);
I completed the 3D earth. Now I am trying to draw a triangle on the earth? but I failed to complete it, could you give me some cues or code to complete it? the following is drawing part in the sphere code. I could draw the triangle on the screen, but I do not know how to draw the triangle or point on the surface of 3D earth to render the latitude and longitude data on the earth.
public void draw(GL10 gl)
{
float vertexArray[] = {
SphereCoordinate(lat1, long1, 2).x,SphereCoordinate(lat1, long1, 2).y,SphereCoordinate(lat1, long1, 2).z,0.0f,
SphereCoordinate(lat2, long2, 2).x,SphereCoordinate(lat2, long2, 2).y,SphereCoordinate(lat2, long2, 2).z,0.0f,
SphereCoordinate(lat3, long3, 2).x,SphereCoordinate(lat3, long3, 2).y,SphereCoordinate(lat3, long3, 2).z,0.0f,
};
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_BLEND);
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(vertexArray));
gl.glColor4f(.0f, 1.0f, 0.0f, 1);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3); // I want to draw the triangle on earth.
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, m_VertexData);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glClientActiveTexture(GL10.GL_TEXTURE0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, m_Texture0);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, m_TextureData);
gl.glClientActiveTexture(GL10.GL_TEXTURE1);
gl.glTexCoordPointer(2, GL10.GL_FLOAT,0,m_TextureData);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, m_NormalData);
gl.glColorPointer(4, GL10.GL_UNSIGNED_BYTE, 0, m_ColorData);
multiTextureBumpMap(gl, m_Texture0, m_Texture1);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, (m_Slices+1)*2*(m_Stacks-1)+2);
}
At the beginning, the SphereCoordinate(lat1, long1, 2(r)), the r is 1 which is equal with radius of sphere, but the triangle could not be viewed. Then I made the r be 2. And run, the final slot is the following image:
Actually, I want to draw the triangle on the surface of earth.
I am a newbie with opengl on android. I am trying to draw two different shapes. Shape one has a texture while shape two is supposed to have a color, lets say green. When I run the application, the first shape gets its texture but has also the green color. The texture itself is turned greenish in color. Shape two is green as i wanted. Here is my draw method:
public void draw(GL10 gl) {
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
//My first shape
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glPushMatrix();
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glPopMatrix();
//My second shape
gl.glPushMatrix();
//Setting the color green
gl.glColor4f(0.0f, 1.0f, 0.0f, 0.5f);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, locvertexBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, locvertices.length / 3);
gl.glPopMatrix();
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
Can anyone help me with this?
Try to put gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); before drawing the first shape
OR
use gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE);
after you bind the texture
UPDATE: Summary:
I can draw a circle using TRIANGLE_FAN and, separately, I also can draw two squares with bitmaps as textures. But the problem is when I draw the textures and then the circles. Circles aren't drawn.
I'm drawing two texturized squares (4 vertex each). Then I draw a circle using GL_TRIANGLE_FAN but it isn't being drawn correctly (see images).
When I draw the circles without the squares, it is drawn correctly.
Any ideas where could be the problem?
Please, ask for more information. Thanks
Adding some code that I think is important:
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glEnable(GL10.GL_BLEND);
gl.glCullFace(GL10.GL_BACK);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnable(GL10.GL_TEXTURE_2D);
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glOrthof(0, w, -0, h, -1, 1);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
circle.draw(gl);
needle.draw(gl);
synchronized (tokens) {
for (Token d : tokens) {
d.draw(gl);
}
}
}
Update:
Some screenshots.
Without drawing circle and needle objects:
Drawing circle and needle:
(Look at those red lines where should be a circle)
The only change in the code between those images is commenting the lines
circle.draw(gl);
needle.draw(gl);
Token:
public void draw(GL10 gl) {
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glPushMatrix();
gl.glTranslatef(x, y, 0f);
gl.glScalef(radius, radius, 0f);
gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, nVertices+2);
gl.glPopMatrix();
}
Circle and Needle:
public void draw(GL10 gl) {
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
if (shouldLoadTexture) {
loadGLTexture(gl);
shouldLoadTexture = false;
}
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
gl.glPushMatrix();
gl.glTranslatef(x, y, 0f);
gl.glRotatef((float) angle, 0f, 0f, 1f);
angle += rotAngle;
if(angle+rotAngle > 360.0)
angle -= 360.0;
gl.glScalef(width, height, 0f);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
gl.glPopMatrix();
}
private void loadGLTexture(GL10 gl) {
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
textureId = textures[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_REPEAT);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
}
Update:
Following what Arne says in the first answer, I changed:
public void draw(GL10 gl) {
//New line
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
if (shouldLoadTexture) {
loadGLTexture(gl);
shouldLoadTexture = false;
}
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
gl.glPushMatrix();
gl.glTranslatef(x, y, 0f);
gl.glRotatef((float) angle, 0f, 0f, 1f);
angle += rotAngle;
if(angle+rotAngle > 360.0)
angle -= 360.0;
gl.glScalef(width, height, 0f);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
gl.glPopMatrix();
//New line
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
Now I get no circle at all. Neither red line as in the second image.
Update:
When I don't load the texture of circle and needle (just commenting the call to loadTexture() ), I get this:
So the problem should be with the textures.
You enable texturing (by calling glEnable(GL_TEXTURE_2D)) at the beginning, but you don't provide your circles (tokens) any texture coordinates. As I suppose these shouldn't be textured, you should only enable texturing for the objects that are really textured and disable texturing again after drawing them, the same way you enable and disable the texCoord array in your updated code.
Try to disable GL_TEXTURE_COORD_ARRAY before drawing the circles with
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
/*
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL10.GL_BLEND);
gl.glEnable(GL10.GL_LINE_SMOOTH);
*/
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glLineWidth(3.0f);
gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, list.size()/3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
//gl.glDisable(GL10.GL_BLEND);
//gl.glDisable(GL10.GL_LINE_SMOOTH);
}
my code is the following.
if i add this code
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL10.GL_BLEND);
gl.glEnable(GL10.GL_LINE_SMOOTH);
then i get a very thin (1px) line, and not an antialised line. what is the best way to do its correctly?
I think what you're doing is correct, but are you sure your device supports anti aliasing? Look at this blog post:
http://olofsj.posterous.com/playing-with-android-and-opengl