Android: OpenGL ES2 текстура не работает - PullRequest
2 голосов
/ 05 ноября 2011

ОБНОВЛЕНИЕ: избавился от строки GLES20.glEnable(GLES20.GL_TEXTURE_2D); Но строка GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, 256, 256, 0, GLES20.GL_RGB, GLES20.GL_BYTE, ByteBuffer.wrap(pixels)); дает GL_INVALID_ENUM ... длина буфера пикселя равна 196608.

Файлы проекта: http://godofgod.co.uk/my_files/NightCamPrj.zip

Япытаясь получить данные камеры в шейдер OpenGL ES2, и кажется, что камера работает, но я не могу заставить текстуру работать, даже когда я пробую свои собственные значения.Я получаю черный экран.Вот код:

package com.matthewmitchell.nightcam;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Scanner;

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

import android.content.Context;
import android.content.res.AssetManager;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;

public class MyRenderer implements GLSurfaceView.Renderer{
    private FloatBuffer vertices;
    private FloatBuffer texcoords;
    private int mProgram;
    private int maPositionHandle;
    private int gvTexCoordHandle;
    private int gvSamplerHandle;
    private static Context context;
    int[] camera_texture;
    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        initShapes();
        GLES20.glClearColor(0.0f, 1.0f, 0.2f, 1.0f);
        Debug.out("Hello init.");
        //Shaders
        int vertexShader = 0;
        int fragmentShader = 0;
        try {
            vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, readFile("vertex.vsh"));
            fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, readFile("fragment.fsh"));
        } catch (IOException e) {
            Debug.out("The shaders could not be found.");
            e.printStackTrace();
        }
        mProgram = GLES20.glCreateProgram();             // create empty OpenGL Program
        GLES20.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program
        Debug.out("VS LOG: " + GLES20.glGetShaderInfoLog(vertexShader)); 
        GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
        Debug.out("FS LOG: " + GLES20.glGetShaderInfoLog(fragmentShader)); 
        GLES20.glLinkProgram(mProgram);                  // creates OpenGL program executables
        Debug.out("PROG LOG: " + GLES20.glGetProgramInfoLog(mProgram)); 
        // get handles
        maPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        gvTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texCoord");
        gvSamplerHandle = GLES20.glGetAttribLocation(mProgram, "s_texture");
        camera_texture = null;
        GLES20.glEnable(GLES20.GL_TEXTURE_2D);
    }


    private void initShapes(){
        float triangleCoords[] = {
            // X, Y, Z
            -1.0f, -1.0f, 0.0f,
             1.0f, -1.0f, 0.0f,
             -1.0f, 1.0f, 0.0f,
             1.0f,  1.0f, 0.0f,
        }; 
        float texcoordf[] = {
            // X, Y, Z
            -1.0f,-1.0f,
            1.0f,-1.0f,
            -1.0f,1.0f,
            1.0f,1.0f,
        }; //Even if wrong way around it should produce a texture with these coordinates on the screen.

        // initialize vertex Buffer for vertices
        ByteBuffer vbb = ByteBuffer.allocateDirect(triangleCoords.length * 4); 
        vbb.order(ByteOrder.nativeOrder());// use the device hardware's native byte order
        vertices = vbb.asFloatBuffer();  // create a floating point buffer from the ByteBuffer
        vertices.put(triangleCoords);    // add the coordinates to the FloatBuffer
        vertices.position(0);            // set the buffer to read the first coordinate
        // initialize vertex Buffer for texcoords 
        vbb = ByteBuffer.allocateDirect(texcoordf.length * 4); 
        vbb.order(ByteOrder.nativeOrder());// use the device hardware's native byte order
        texcoords = vbb.asFloatBuffer();  // create a floating point buffer from the ByteBuffer
        texcoords.put(texcoordf);    // add the coordinates to the FloatBuffer
        texcoords.position(0);            // set the buffer to read the first coordinate
    }

    private static String readFile(String path) throws IOException {
        //Load file from assets folder using context given by the activity class
        AssetManager assetManager = context.getAssets();
        InputStream stream = assetManager.open(path);
        try {
            return new Scanner(stream).useDelimiter("\\A").next();
        }
        finally {
            stream.close();
        }
    }

    private int loadShader(int type, String shaderCode){
        int shader = GLES20.glCreateShader(type);
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);
        return shader;
    }

    public void onDrawFrame(GL10 unused) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        if(camera_texture == null){
            return;
        }
        // Add program to OpenGL environment
        GLES20.glUseProgram(mProgram);
        // Prepare the triangle data
        GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertices);
        GLES20.glVertexAttribPointer(gvTexCoordHandle, 2, GLES20.GL_FLOAT, false, 0, texcoords);
        GLES20.glEnableVertexAttribArray(maPositionHandle);
        GLES20.glEnableVertexAttribArray(gvTexCoordHandle);
        //Bind texture
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, camera_texture[0]);
        GLES20.glUniform1i(gvSamplerHandle, 0);
        // Draw the triangle
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
        //Disable arrays
        GLES20.glDisableVertexAttribArray(maPositionHandle);
        GLES20.glDisableVertexAttribArray(gvTexCoordHandle);
    }

    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
    }

    public void takeContext(Context mcontext) {
        context = mcontext;
    }

    void bindCameraTexture(byte[] data,int w,int h) {
        //Takes pixel data from camera and makes texture
        byte[] pixels = new byte[256*256*3]; //Testing simple 256x256 texture. Will update for camera resolution
        for(int x = 0;x < 256;x++){
            for(int y = 0;y < 256;y++){
                //Ignore camera data, use test values.
                pixels[(x*256+y)*3] = 0;
                pixels[(x*256+y)*3+1] = 100;
                pixels[(x*256+y)*3+2] = 120;
            }
        }
        //Debug.out("PX:" + pixels[0] + " " + pixels[1] + " " + pixels[2]);
        //Make new texture for new data
        if (camera_texture == null){
            camera_texture = new int[1];
        }else{
            GLES20.glDeleteTextures(1, camera_texture, 0);
        }
        GLES20.glGenTextures(1, camera_texture, 0);
        int tex = camera_texture[0];
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex);
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, 256, 256, 0, GLES20.GL_RGB, GLES20.GL_BYTE, ByteBuffer.wrap(pixels));
        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);
    }
}

Вот код вершинного шейдера:

attribute vec4 vPosition;
attribute vec2 a_texCoord;
varying vec2 v_texCoord;
void main(){ 
    gl_Position = vPosition;
    v_texCoord = a_texCoord;
}    

Вот код фрагмента шейдера:

precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main(){
    gl_FragColor = texture2D(s_texture, v_texCoord);
}

Мы можем игнорироватькамера здесь, потому что я использую тестовые значения.Я использую тестовую текстуру 256x256.Я сделал все, что видел в примерах.

Почему он черный и как я могу его показать?

Ответы [ 3 ]

3 голосов
/ 10 ноября 2011

Я вижу, что вы используете glGetAttribLocation() для получения местоположения s_texture. Это единообразная переменная, а не атрибут. Попробуйте использовать glGetUniformLocation() вместо этого.

Я не знаю, решит ли это все ваши проблемы, но это обязательно нужно сделать.

3 голосов
/ 08 ноября 2011

это не видно из вашего кода, но мне кажется, что вы не вызываете bindCameraTexture из того места, где находится контекст рендеринга (в то время как вы должны делать это в onSurfaceCreated или onSurfaceChanged).

0 голосов
/ 23 июля 2013

Я закончил пример с предварительным просмотром камеры в качестве текстуры.ключевое различие с вашим кодом:

  1. Я использую SurfaceTexture для подключения предварительного просмотра камеры к текстуре, используемой в openGL ES.
  2. Я использую матрицу, сгенерированную SurfaceTexture, для настройкивывод предварительного просмотра камеры, в противном случае появляется черная область мерцания.
  3. Я не вызываю glBindTexture () явно для текстуры, используемой для предварительного просмотра камеры.

    Удачи.

...