Log in or register to post comments

Dynamically created texture showing up black

July 17, 2014 - 11:02am #1

Hello all,

 

Long time lurker, first time poster, experienced in android, newbie++ with vuforia, newbie with OpenGL.

 

My goal is to display text on a frame marker.  After reading countless of posts, forums, blogs, etc, I decided on using the method where a texture is created with my text on it, loading the texture, and displaying it.

Since I am starting out and i read a lot of information on the topic, I am creating a 256x256 bitmap with my text on it.  I saved it on my android device after creating it to check that the image is created correctly and with the right colors and dimensions.  I then load it into the mTextures, but whenever I try to display it, I get a black image (02_custom_texture_not_displayed.png).

I have also loaded other textures onto the 2D sample object provided by Vuforia, so it works with the textures that Vuforia includes for the sample apps like letter_Q.png and letter_A.png.  It just refuses to work with my generated png, even though it is the same size and format as letter_Q.png (01_letterQ_texture_display.png).

The only time it has ever "worked" is after working on my android device for a few hours and my device gets "tired."  the screen changes from camera view to all white, then to all black, then resumes camera view.  once the app finds the frame marker, the image i created works properly. (03_custom_texture_desired_display.png) This has only happened to me twice so far, which leads me to believe that the texture is loading correctly, im just missing something.  it's like when a computer's graphics driver dies and recovers, and has to redraw everything on screen.

my openGL knowledge isn't great, but i understand the concept and some of the processing.  If i use another of the preloaded textures, everything works without any issues. am i saving my custom image correctly?  am I loading textures incorrectly?  is there a setting that needs to be cleared/reset?

Thanks for any help!  Please let me know if anyone has questions!

    void renderFrame()
    {
        // Clear color and depth buffer
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        
        // Get the state from Vuforia and mark the beginning of a rendering
        // section
        State state = Renderer.getInstance().begin();
        
        // Explicitly render the Video Background
        Renderer.getInstance().drawVideoBackground();
        
        GLES20.glEnable(GLES20.GL_DEPTH_TEST);
        
        // We must detect if background reflection is active and adjust the
        // culling direction.
        // If the reflection is active, this means the post matrix has been
        // reflected as well,
        // therefore standard counter clockwise face culling will result in
        // "inside out" models.
        GLES20.glEnable(GLES20.GL_CULL_FACE);
        GLES20.glCullFace(GLES20.GL_BACK);
        if (Renderer.getInstance().getVideoBackgroundConfig().getReflection() == VIDEO_BACKGROUND_REFLECTION.VIDEO_BACKGROUND_REFLECTION_ON)
            GLES20.glFrontFace(GLES20.GL_CW);  // Front camera
        else
            GLES20.glFrontFace(GLES20.GL_CCW);   // Back camera
            
        // Did we find any trackables this frame?
        for (int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++)
        {
         // if bitmap not created, do it now
         if (!mBitmapCreated) {
        // Create an empty, mutable bitmap
        Bitmap bitmap = Bitmap.createBitmap(256, 256, Bitmap.Config.ARGB_8888);
        // get a canvas to paint over the bitmap
        Canvas canvas = new Canvas(bitmap);
        //bitmap.eraseColor(0);

        // get a background image from resources
        // note the image format must match the bitmap format
        // R.drawable.background is a solid red 256x256 png 
        Drawable background = mActivity.getBaseContext().getResources().getDrawable(R.drawable.background);
        background.setBounds(0, 0, 256, 256);
        background.draw(canvas); // draw the background to our bitmap

        // Draw the text
        Paint textPaint = new Paint();
        textPaint.setTextSize(32);
        textPaint.setAntiAlias(true);
        textPaint.setARGB(0xFF, 0x40, 0xFF, 0x40);
        // draw the text centered
        canvas.drawText("Hello World", 16,112, textPaint);
        
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int[] data = new int[bitmap.getWidth() * bitmap.getHeight()];
        
        bitmap.getPixels(data, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
                    
        // recycle bitmap, no longer needed
        bitmap.recycle();
        bitmap = null;
        
        texNew = Texture.loadTextureFromIntBuffer(data, 256, 256);
        mTextures.add(texNew);
        
        mBitmapCreated = true;
         }

            // Get the trackable:
            TrackableResult trackableResult = state.getTrackableResult(tIdx);
            
            float[] modelViewMatrix = Tool.convertPose2GLMatrix(
                trackableResult.getPose()).getData();
            
            Log.d(LOGTAG, "modelViewMatrix" + modelViewMatrix.toString());
            
            // Choose the texture based on the target name:
            int textureIndex = 0;
            
            // Check the type of the trackable:
            assert (trackableResult.getType() == MarkerTracker.getClassType());
            MarkerResult markerResult = (MarkerResult) (trackableResult);
            Marker marker = (Marker) markerResult.getTrackable();
            
            textureIndex = marker.getMarkerId();
            
            assert (textureIndex < mTextures.size());
            Log.d(LOGTAG, "textures size: " + mTextures.size());

            Texture thisTexture;
            
            // if new bitmap created, use new texture
            if (mBitmapCreated) {
             thisTexture = mTextures.lastElement();
            } else {
             // use default texture
             thisTexture = mTextures.get(textureIndex);
            }
            
            // Select which model to draw:
            Buffer vertices = null;
            Buffer normals = null;
            Buffer indices = null;
            Buffer texCoords = null;
            int numIndices = 0;
            
            switch (marker.getMarkerId())
            {
                case 0:
                        // replaced Q object 
                        vertices = dObject.getVertices();
                        normals = dObject.getNormals();
                        indices = dObject.getIndices();
                        texCoords = dObject.getTexCoords();
                        numIndices = dObject.getNumObjectIndex();
                        break;
                case 1:
                    vertices = cObject.getVertices();
                    normals = cObject.getNormals();
                    indices = cObject.getIndices();
                    texCoords = cObject.getTexCoords();
                    numIndices = cObject.getNumObjectIndex();
                    break;
                case 2:
                    vertices = aObject.getVertices();
                    normals = aObject.getNormals();
                    indices = aObject.getIndices();
                    texCoords = aObject.getTexCoords();
                    numIndices = aObject.getNumObjectIndex();
                    break;
                default:
                    vertices = rObject.getVertices();
                    normals = rObject.getNormals();
                    indices = rObject.getIndices();
                    texCoords = rObject.getTexCoords();
                    numIndices = rObject.getNumObjectIndex();
                    break;
            }
            
            float[] modelViewProjection = new float[16];
            
            if (mActivity.isFrontCameraActive())
                Matrix.rotateM(modelViewMatrix, 0, 180, 0.f, 1.0f, 0.f);
            
            Matrix.translateM(modelViewMatrix, 0, -kLetterTranslate,
                    -kLetterTranslate, 0.f);
            Matrix.scaleM(modelViewMatrix, 0, kLetterScale, kLetterScale,
                kLetterScale);
            Matrix.multiplyMM(modelViewProjection, 0, vuforiaAppSession
                .getProjectionMatrix().getData(), 0, modelViewMatrix, 0);
            
            GLES20.glUseProgram(shaderProgramID);
            
            GLES20.glVertexAttribPointer(vertexHandle, 3, GLES20.GL_FLOAT,
                false, 0, vertices);
            GLES20.glVertexAttribPointer(normalHandle, 3, GLES20.GL_FLOAT,
                false, 0, normals);
            GLES20.glVertexAttribPointer(textureCoordHandle, 2,
                GLES20.GL_FLOAT, false, 0, texCoords);
            
            GLES20.glEnableVertexAttribArray(vertexHandle);
            GLES20.glEnableVertexAttribArray(normalHandle);
            GLES20.glEnableVertexAttribArray(textureCoordHandle);
                        
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,
                thisTexture.mTextureID[0]);
            GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false,
                modelViewProjection, 0);
            GLES20.glUniform1i(texSampler2DHandle, 0);
            GLES20.glDrawElements(GLES20.GL_TRIANGLES, numIndices,
                GLES20.GL_UNSIGNED_SHORT, indices);
            
            GLES20.glDisableVertexAttribArray(vertexHandle);
            GLES20.glDisableVertexAttribArray(normalHandle);
            GLES20.glDisableVertexAttribArray(textureCoordHandle);
            
            SampleUtils.checkGLError("FrameMarkers render frame");
            
        }
        
        GLES20.glDisable(GLES20.GL_DEPTH_TEST);
        
        Renderer.getInstance().end();
        //i++;
       // }
    }

 

Dynamically created texture showing up black

May 30, 2017 - 9:02am #9

Hi CarterBao,

In my case, I was trying to call methods of GLES20 from UI thread which was creating the same problem of showing model with black.

I fixed it using enqueEvent() of GLSurfaceView to execute texture binding commands.

 

mGlView.queueEvent(new Runnable() {

      @Override

      public void run() { 

GLES20.glGenTextures(1, currentTexture.mTextureID, 0);

    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, currentTexture.mTextureID[0]);

    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,

            GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);

    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,

            GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,

            GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);

    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,

            GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,

            currentTexture.mWidth, currentTexture.mHeight, 0, GLES20.GL_RGBA,

            GLES20.GL_UNSIGNED_BYTE, currentTexture.mData); 

 

}

    });

Dynamically created texture showing up black

May 30, 2017 - 6:36am #8

Hi CarterBao,

In my case, below two lines were messing up the rendering of texture dynamically. When I removed these lines, it worked fine. :) Thanks for your answer. This problem wasted my one day.

GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,

            GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);

    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,

            GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

Dynamically created texture showing up black

August 13, 2016 - 3:11am #7

Hi! I just solved this problem and I'd like to share my methods with you. The key problem is not about the texture size( it doesn't need to be size of power of 2).

I worked on the ImageTargets sample, and I needed to get dynamic textures from a server through TCP link. After I dynamically load the texture into mTexture in ImageTarget.java like this( I referred to the loadTextureFromApk() function and wrote the loadTextureFromByteArray() function ):

            mTextures.set(0,Texture.loadTextureFromByteArray(buffer,offset,texLen));

I added the following codes into the begining of renderFrame() function in ImageTargetRenderer.java, to generate a new texture and bind it to GLES20.GL_TEXTURE_2D, and it worked! 

            GLES20.glGenTextures(1, mTextures.get(0).mTextureID, 0);

            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures.get(0).mTextureID[0]);

            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,

                    GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);

            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,

                    GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,

                    mTextures.get(0).mWidth, mTextures.get(0).mHeight, 0, GLES20.GL_RGBA,

                    GLES20.GL_UNSIGNED_BYTE, mTextures.get(0).mData);

Before that, I tried to call initRendering() after the texture is loaded, but it didn't work. I also tried to change my texture into 512*512 size, which didn't work either.

I've been searching for the solution for almost two days and finally I fixed it with myself! Hope this can help you. 

This solution may cost lots of CPU time and I'm looking for a faster solution.

Dynamically created texture showing up black

August 30, 2014 - 3:40am #6

Hello!!

i haven't found in this forum any solution about my problem. 

i have proved when i store the textures in APK and works fine. My problem is when i store the textures from server in Vector<Texture> mTextures. The dimensions used are 256x256 in texture plane and 630x340 in textures from video. The video plays correctly in the marker only my problem is about draw textures. i don't know what i need!! 

I load all the textures that i need using AsyncTask connecting my app with my server. Then, when i have all the textures in Vector<Textures> mTextures i call the part of rendering. Have i to call initRendering() in each texture, after mTextures.add(Texture.loadTextureFromIntBuffer(data, width, height)); ??? i don't know how to do that!  

Any suggestions please?? Administrator??

Thanks for advice!!!

Dynamically created texture showing up black

August 20, 2014 - 7:05pm #5

Thanks rawsteak for your quickly reply!

your solution is not that i want to do! I take information from a database with JSON( something how the url where my texture are loaded). i want to load textures from a server because i need a dinamic application. First download the image from the server. I have follow Books Sample to download image in Bitmap format but i don't know how render this textures correctly. I store the textures in a Vector<Textures> and this Vector have a size later i store this textures. but when my application is rendered this textures appear totally in black but in the correct position, inside the frame marker and if this texture corresponds to a video when I touch the screen inside the frame marker the video is played perfectly and moreover the dimension are correct too. i think but the problem refers to draw the textures over the frame because first i proved load the textures from APK like in the samples and work correctly. 

Thanks in advanse!!

 

Dynamically created texture showing up black

August 20, 2014 - 8:26am #4

Have you tried adding initRendering() right after loading the texture?

        mTextures.add(Texture.loadTextureFromSDCard("texRender" + intMarkerID + ".PNG"));
        initRendering();

that's exactly what I put in my program.  I don't know if there is a more elegant or appropriate way of doing it, but that's what works for my program.  of course, I also have code the determines if a texture has been loaded so I don't keep calling initRendering().  it doesn't reset the app or clear any other textures you loaded.  Please let us know if it works or you find some other solution!

Dynamically created texture showing up black

August 19, 2014 - 12:16pm #3

Hi everybody!!

Now i am developing an application that it load the textures from a server and a database using Objects JSON. I have follow the sample Books in order to download a image in Bitmap. Then i want to show this textures in a frame marker but i have the similar problem. 

I have loaded the textures in a Vector<Texture> with  mTextures.add(Texture.loadTextureFromIntBuffer(data, width, height)); and when the application render appeared the texture in the correct marker defined but totally in black. 

i don't know how to solve this problem!! i have taken some time reading a lot of forums about Canvas, the View to draw the texture. I am very lost!! 

Somebody knows how solve it!! Thanks!!

Dynamically created texture showing up black

July 18, 2014 - 1:23pm #2

I kind of found a solution... maybe?

I was going through forum threads and found this one: https://developer.vuforia.com/forum/rendering-opengl-es/set-mtextures-after-initial-call

ksiva points out that after adding the new texture(s) "The trick here is that these GL textures must be generated on the GLThread, so if you are updating your textures from the main activity thread you'll need to do something like this:" and then an example of updating mRenderer.  In my application, I am updating it from FrameRenderer, so I wasn't able to make the connection.  In order to update the new texture I added, I now run initRendering().

Now my app displays the dynamic picture that I created and displays correctly.  As I suspected, it was being drawn correctly, it just wasn't updating to the app correctly, and this thread pointed out where it wasn't getting picked up.

Is there anyone else that is also attempting the same goal?  what other ways is this possible?

Log in or register to post comments