search
HomeJavaOpenGL ES 3.0 - black texture

This java Q&A brought by editor Yuzai will focus on the issues related to black texture in OpenGL ES 3.0. In OpenGL ES 3.0, texture processing is an important topic, and the black texture problem is also one of the challenges developers often encounter. This article will provide a detailed answer to this question to help developers better understand and resolve related doubts.

Question content

I try to render a simple texture .png on a square, but it always appears black. In my example code, 2 squares are rendered, one with the texture wall.png and the second with a 4 pixel byte buffer for testing. I checked some pixels and sizes of the bitmap and they are all fine. 4 pixel byte buffer is working, but weird glitches occur. The byte buffer requires 2 extra bytes of data, I don't know what's causing it.

thanks for your help! ! !

package com.example.opengles3_test1;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.util.Log;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class Renderer_Texture implements GLSurfaceView.Renderer {
    private static String TAG = "Renderer"; //For LOG
    final int VERTEX_POS_SIZE = 3; // x, y and z
    final int VERTEX_COLOR_SIZE = 4; // r, g, b, and a
    final int VERTEX_TEXTUR_SIZE=2; //x,y
    final int VERTEX_POS_INDX = 0;
    final int VERTEX_COLOR_INDX = 1;
    final int VERTEX_TEXTUR_INDX = 2;
    final int VERTEX_STRIDE = (4 * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE+VERTEX_TEXTUR_SIZE));
    // 3 vertices, with (x,y,z) ,(r, g, b, a), (x,y) per-vertex
    final int[] textures = new int[2];
    private final float[] mVerticesData =
            {
            // positions          // colors           // texture coords
            -0.1f,  0.4f, 0.0f,   1.0f, 0.0f, 0.0f, 1.0f,  1.0f, 1.0f, // top right
            -0.1f, -0.4f, 0.0f,   0.0f, 1.0f, 0.0f, 1.0f,  1.0f, 0.0f, // bottom right
            -0.8f, -0.4f, 0.0f,   0.0f, 0.0f, 1.0f, 1.0f,  0.0f, 0.0f, // bottom left
            -0.8f,  0.4f, 0.0f,   1.0f, 1.0f, 0.0f, 1.0f,  0.0f, 1.0f  // top left

            };
    private final float[] mVerticesData2 =
            {
                    // positions          // colors           // texture coords
                    0.8f,  0.4f, 0.0f,   1.0f, 0.0f, 0.0f, 1.0f,  1.0f, 1.0f, // top right
                    0.8f, -0.4f, 0.0f,   0.0f, 1.0f, 0.0f, 1.0f,  1.0f, 0.0f, // bottom right
                    0.1f, -0.4f, 0.0f,   0.0f, 0.0f, 1.0f, 1.0f,  0.0f, 0.0f, // bottom left
                    0.1f,  0.4f, 0.0f,   1.0f, 1.0f, 0.0f, 1.0f,  0.0f, 1.0f  // top left

            };
      private final short[] mIndicesData =
            {
                    0, 1, 3 , 1, 2, 3
            };
    ShaderV1 Shaderprog1;
    private int[] VBOIds = new int[4]; // VertexBufferObject Ids
    private int[] VAOId = new int[2]; // VertexArrayObject Id
       private int mWidth;
    private int mHeight;
    private FloatBuffer mVertices;
    private ShortBuffer mIndices;
    private FloatBuffer mVertices2;

    public Renderer_Texture(Context context) {
        mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
        mVertices.put(mVerticesData).position(0);
        mVertices2 = ByteBuffer.allocateDirect(mVerticesData2.length * 4)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
        mVertices2.put(mVerticesData2).position(0);
        mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2)
                .order(ByteOrder.nativeOrder()).asShortBuffer();
        mIndices.put(mIndicesData).position(0);
    }

        private static Bitmap convertBitmapToConfig(Bitmap bitmap, Bitmap.Config config) {
            if (bitmap.getConfig() == config) {
                return bitmap;
            }
            Bitmap result = bitmap.copy(config, false);
            bitmap.recycle();
            return result;
        }

    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {

        Shaderprog1= new ShaderV1("res/raw/vertext_shader1.vs", "res/raw/fragment_shader1.fs");

        GLES30.glGenBuffers(4, VBOIds, 0);
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, VBOIds[0]);
        mVertices.position(0);
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, mVerticesData.length * 4,
                mVertices, GLES30.GL_STATIC_DRAW);
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, VBOIds[1]);
        mIndices.position(0);
        GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, 2 * mIndicesData.length,
                mIndices, GLES30.GL_STATIC_DRAW);

        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, VBOIds[2]);
        mVertices2.position(0);
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, mVerticesData2.length * 4,
                mVertices2, GLES30.GL_STATIC_DRAW);

        GLES30.glGenVertexArrays(2, VAOId, 0);

        GLES30.glBindVertexArray(VAOId[0]);
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, VBOIds[0]);
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, VBOIds[1]);
        GLES30.glEnableVertexAttribArray(VERTEX_POS_INDX);
        GLES30.glEnableVertexAttribArray(VERTEX_COLOR_INDX);
        GLES30.glEnableVertexAttribArray(VERTEX_TEXTUR_INDX);
        GLES30.glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE,
                GLES30.GL_FLOAT, false, VERTEX_STRIDE,
                0);
        GLES30.glVertexAttribPointer(VERTEX_COLOR_INDX, VERTEX_COLOR_SIZE,
                GLES30.GL_FLOAT, false, VERTEX_STRIDE,
                (VERTEX_POS_SIZE * 4));
        GLES30.glVertexAttribPointer(VERTEX_TEXTUR_INDX, VERTEX_TEXTUR_SIZE,
                GLES30.GL_FLOAT, false, VERTEX_STRIDE,
                (VERTEX_POS_SIZE * 4+VERTEX_COLOR_SIZE*4));
        //second:
        GLES30.glBindVertexArray(VAOId[1]);
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, VBOIds[2]);
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, VBOIds[1]);
        GLES30.glEnableVertexAttribArray(VERTEX_POS_INDX);
        GLES30.glEnableVertexAttribArray(VERTEX_COLOR_INDX);
        GLES30.glEnableVertexAttribArray(VERTEX_TEXTUR_INDX);
        GLES30.glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE,
                GLES30.GL_FLOAT, false, VERTEX_STRIDE,
                0);
        GLES30.glVertexAttribPointer(VERTEX_COLOR_INDX, VERTEX_COLOR_SIZE,
                GLES30.GL_FLOAT, false, VERTEX_STRIDE,
                (VERTEX_POS_SIZE * 4));
        GLES30.glVertexAttribPointer(VERTEX_TEXTUR_INDX, VERTEX_TEXTUR_SIZE,
                GLES30.GL_FLOAT, false, VERTEX_STRIDE,
                (VERTEX_POS_SIZE * 4+VERTEX_COLOR_SIZE*4));
        // Reset to the default VAO
        GLES30.glBindVertexArray(0);

        GLES30.glClearColor(0.2f, 0.2f, 0.2f, 0.0f);

        GLES30.glGenTextures(2, textures,0);
        if (textures[0] == 0) {
           Log.e(TAG,"could not bind texture");
           return;
        }
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[0]);
        // set the texture wrapping parameters
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
        // set texture filtering parameters
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);

            Bitmap bitmap = null;
            try {
                bitmap =convertBitmapToConfig(BitmapFactory.decodeStream(ShaderV1.class.getClassLoader().getResourceAsStream("res/raw/wall.jpg")), Bitmap.Config.ARGB_8888);
                ByteBuffer buffer = ByteBuffer.allocateDirect(bitmap.getByteCount());
                bitmap.copyPixelsToBuffer(buffer);
                buffer.rewind();
                GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[0]);
                GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D,0, GLES30.GL_RGB, bitmap.getWidth(), bitmap.getHeight(),  0,  GLES30.GL_RGBA,  GLES30.GL_UNSIGNED_BYTE, buffer);
                //Log.e(TAG,"pixel "+ String.format("#%06X", (0xFFFFFF & bitmap.getPixel(200,200)))); //looks correct
                //Log.d(TAG,"bitmapsize:" + bitmap.getWidth() +" " + bitmap.getHeight()); //looks correct
                GLES30.glGenerateMipmap(GLES30.GL_TEXTURE_2D);
            } catch (Exception e) {
                Log.e(TAG,"texture error "+ e.getLocalizedMessage());
            } finally {
                if (bitmap != null) {
                    bitmap.recycle();
                }
            }
                byte[] bytes = {
            //  R           G            B      
                (byte) 0xcf,(byte) 0x00,(byte) 0x00,  //EDGE 1
                (byte) 0x8f,(byte) 0x00,(byte) 0x50,(byte) 0x00,(byte) 0x00, //EDGE 2 WTF 2 extra?!?
                (byte) 0x5f,(byte) 0x80,(byte) 0x00, //EDGE 3
                (byte) 0x3f,(byte) 0x00,(byte) 0x80}; //EDGE 4
        ByteBuffer b = ByteBuffer.wrap(bytes);

        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[1]);
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE); //GLES30.GL_REPEAT also work
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE); //GLES30.GL_REPEAT also work
        // set texture filtering parameters
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);

        GLES30.glTexImage2D ( GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGB, 2, 2, 0, GLES30.GL_RGB, GLES30.GL_UNSIGNED_BYTE, b );
        GLES30.glGenerateMipmap(GLES30.GL_TEXTURE_2D);
            Shaderprog1.use();
        GLES30.glUniform1i(GLES30.glGetUniformLocation(Shaderprog1.getID(), "texture1"), 0);
    }

    public void onDrawFrame(GL10 glUnused) {
        GLES30.glViewport(0, 0, mWidth, mHeight);
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);

        GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[1]);
        Shaderprog1.use();

        GLES30.glBindVertexArray(VAOId[0]);
        GLES30.glDrawElements(GLES30.GL_TRIANGLES, mIndicesData.length, GLES30.GL_UNSIGNED_SHORT, 0);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[0]);
        GLES30.glBindVertexArray(VAOId[1]);
        GLES30.glDrawElements(GLES30.GL_TRIANGLES, mIndicesData.length, GLES30.GL_UNSIGNED_SHORT, 0);

        GLES30.glBindVertexArray(0);
    }

    public void onSurfaceChanged(GL10 glUnused, int width, int height) {
        mWidth = width;
        mHeight = height;
        Log.d ( TAG, width +" "+ height );
    }
}

Screenshot

Solution

android provides a simple API for loading bitmaps as opengl textures:

GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0);

EDIT: You can find more information about this herehttps://www.php.cn/link/afd7de3f825e55b48cbc839e095326a4

The above is the detailed content of OpenGL ES 3.0 - black texture. For more information, please follow other related articles on the PHP Chinese website!

Statement
This article is reproduced at:stackoverflow. If there is any infringement, please contact admin@php.cn delete

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Tools

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

SublimeText3 English version

SublimeText3 English version

Recommended: Win version, supports code prompts!

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool