OpenGL ES 2.0 – Texturas siempre negras
He estado leyendo mucho sobre texturas en Open GL ES 2.0 hoy. Mi problema es que son todos negros.
Mi código:
- ¿Cuál es el parámetro "offset" en GLES20.glVertexAttribPointer / glDrawElements, y de dónde proviene ptr / indices?
- Android opengl-es-2.0 - explicación rotateM
- Android OpenGL2.0 que muestra texturas negras
- ¿Cómo aprender y usar OpenGL ES 2.0? Simplemente no lo entiendo - Qn serio.
- ¿Cómo acceder a OpenGL ES 2 a través de C ++ / NDK si EGL_NATIVE_RENDERABLE no es compatible?
Para generar una textura desde un mapa de bits:
private void generateTexture(Bitmap bmp) { final int[] textureHandle = new int[1]; Log.d(TAG, "Generating texture handle"); GLES20.glGenTextures(1, textureHandle, 0); if (textureHandle[0] != 0) { Log.d(TAG, "binding texture to " + textureHandle[0]); // Bind to the texture in OpenGL GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]); Log.d(TAG, "GLError@bindTex=" + GLES20.glGetError()); // Set filtering GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); Log.d(TAG, "Loading bitmap into texture"); // Load the bitmap into the bound texture. GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0); Log.d(TAG, "GLError@texImg2D=" + GLES20.glGetError()); Log.d(TAG, "Recycle bitmap"); // Recycle the bitmap, since its data has been loaded into OpenGL. bmp.recycle(); }
No hay errores en mi logcat, todo parece ser como se supone que.
Cómo uso la textura:
if (mShader instanceof Texture2DShader && mTextureBuffer != null) { // activate texture Log.d(TAG, "Passing texture stuff"); mTextureBuffer.position(0); Log.d(TAG, "Activate Texture"); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); Log.d(TAG, "Binding texture -> " + mTexture.getHandle()); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexture.getHandle()); if (mShader.getGLLocation(BaseShader.U_TEXTURE) != -1) { Log.d(TAG, "Passing u_Texture"); GLES20.glUniform1i(mShader.getGLLocation(BaseShader.U_TEXTURE), 0); } if (mShader.getGLLocation(BaseShader.A_TEXCOORDINATE) != -1) { Log.d(TAG, "Passing a_TexCoordinate"); GLES20.glVertexAttribPointer(mShader.getGLLocation(BaseShader.A_TEXCOORDINATE), 2, GLES20.GL_FLOAT, false, 0, mTextureBuffer); GLES20.glEnableVertexAttribArray(mShader.getGLLocation(BaseShader.A_TEXCOORDINATE)); } Log.d(TAG, "Texture stuff passed."); Log.d(TAG, "Error = " + GLES20.glGetError()); }
Logcat dice algo como esto:
D/TextureCube﹕ Activate Texture D/TextureCube﹕ Binding texture -> 3 D/TextureCube﹕ Passing u_Texture D/TextureCube﹕ Passing a_TexCoordinate D/TextureCube﹕ Texture stuff passed. D/TextureCube﹕ Error = 0
Así que no hay error, parece estar funcionando?
Mis shaders:
Sombreador de fragmentos:
precision mediump float; // Set the default precision to medium. We don't need as high of a // precision in the fragment shader. uniform vec3 u_LightPos; // The position of the light in eye space. uniform vec4 u_Light; uniform vec4 u_Ambient; uniform vec3 u_LightDirection; uniform vec3 u_CameraPos; uniform sampler2D u_Texture; //varying vec4 v_Ambient; // Ambient light factor! varying vec2 v_TexCoordinate; varying vec3 v_Position; // Interpolated position for this fragment. varying vec4 v_Color; // This is the color from the vertex shader interpolated across the triangle per fragment. varying vec3 v_Normal; // Interpolated normal for this fragment. //varying vec3 v_CameraPosition; // The entry point for our fragment shader. void main() { // Will be used for attenuation. float distance = length(u_LightPos - v_Position); // Get a lighting direction vector from the light to the vertex. vec3 lightVector = normalize(u_LightPos - v_Position); // 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(v_Normal, lightVector), 0.1); // Add attenuation. (used to be 0.25) diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance))); // calculate specular light! //vec3 lightDirection = -u_LightDirection; //vec3 vertexToEye = normalize(u_CameraPos - v_CameraPos); //vec3 lightReflect = normalize(reflect(u_LightDirection, v_Normal)); //float specularFactor = dot(vertexToEye, lightReflect); // Multiply the color by the diffuse illumination level to get final output color. // gl_FragColor = v_Color * (u_Ambient + (diffuse * u_Light) * texture2D(u_Texture, v_TexCoordinate)); }
Vertex Shader:
uniform mat4 u_MVPMatrix; // A constant representing the combined model/view/projection matrix. uniform mat4 u_MVMatrix; // A constant representing the combined model/view matrix. attribute vec4 a_Position; // Per-vertex position information we will pass in. attribute vec4 a_Color; // Per-vertex color information we will pass in. attribute vec3 a_Normal; // Per-vertex normal information we will pass in. attribute vec2 a_TexCoordinate; varying vec2 v_TexCoordinate; varying vec3 v_Position; // This will be passed into the fragment shader. varying vec4 v_Color; // This will be passed into the fragment shader. varying vec3 v_Normal; // This will be passed into the fragment shader. //varying vec3 v_CameraPosition; //varying vec4 v_Ambient; // Pass the ambient color to the fragment shader. // The entry point for our vertex shader. void main() { // Transform the vertex into eye space. v_Position = vec3(u_MVMatrix * a_Position); v_TexCoordinate = a_TexCoordinate; // Pass through the color. v_Color = a_Color; // Transform the normal's orientation into eye space. v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0)); //v_CameraPos = vec3(u_MVMatrix * vec4(u_CameraPos, 0.0)); // v_CameraPosition = u_CameraPos; // 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; }
Parece que texture2D devuelve un vector cero en el shader de fragmentos, ya que si simplemente escribo gl_FragColor = vec4(0.5,0.5,0.5,1.0) + texture2D(..)
se dibuja.
Ya he mirado un sinnúmero de preguntas aquí en SO, así como otros sitios web, sé que esta pregunta exacta se ha hecho un par de veces, pero no importa lo que he intentado – no ayudó.
Ya he bajado mi textura a 512×512, luego 256×256, e incluso más bajo hasta 64×64 pero sin cambios. He imprimido mis manipuladores de textura, revisado para errores de GL, etc., pero nada.
EDITAR:
Al principio he estado intentando cargar la textura de R.raw, después la moví a R.drawable, pero ningún cambio.
EDIT 2: Vertices de los cubos / normals / texture / color declaration:
private final float[] mCubePosition = { // Front face -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, // Right face 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, // Back face 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, // Left face -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, // Top face -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, // Bottom face 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, }; // R, G, B, A private final float[] mCubeColors = { // Front face (red) 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Right face (green) 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, // Back face (blue) 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Left face (yellow) 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // Top face (cyan) 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom face (magenta) 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; private final float[] mCubeNormals = { // Front face 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Right face 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Back face 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, // Left face -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // Top face 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // Bottom face 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f }; private final float[] mCubeTexture = { // Front face 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, // Right face 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, // Back face 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, // Left face 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, // Top face 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, // Bottom face 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f };
EDIT 3: Textura Coordenadas como colores para ver si se están transmitiendo:
gl_FragColor = vec4(v_TexCoordinate.x, v_TexCoordinate.y, 0, 1);
en el fragmento de sombreado resulta en:
- GLSL ES falla las variables locales?
- No se puede lograr 60fps rendering quad simple, Android, Opengl ES 2.0
- Algunos tutoriales para OpenGL ES 2 en Android con NDK?
- ¿Textura al revés? | OpenGL-ES 2.0 (Android)
- ¿Qué versiones de GLSL puedo usar en OpenGL ES 2.0?
- EGL trabajando en Linux pero no en Android
- Google Maps Android API V2 no muestra mapas en Emulator
- Cómo renderizar la imagen de la cámara YUV-NV21 de Android en el fondo en libgdx con OpenGLES 2.0 en tiempo real?
esto es un problema muy común entonces usted no trabaja con la energía de 2 texturas (pixel sabio).
Para no repetir aquí la misma solución ya proporcionada, por favor eche un vistazo a mi respuesta anterior sobre este asunto.
Android OpenGL2.0 que muestra texturas negras
Espero que esto solucione su problema.
Saludos Maurizio
Ok, encontré la solución. Estaba de nuevo confundido por la forma en que funciona el hilo de OpenGL. Yo estaba cargando el Bitmap en un hilo, luego usando glView.post();
para publicar un runnable de nuevo a la (lo que pensé) hilo de OpenGL, donde la textura se supone que se genera y vinculado a la bitmap.
Esto no funciona. Lo que debería haber hecho es:
GLSurfaceView glView = ...; glView.queueEvent(new Runnable() { @Override public void run() { generateTexture(bitmap); } });
Donde en generateTexture, ejecuto todas las cosas GLES20.generateTexture
etc, ya que con queueEvent, es de nuevo en el hilo de OpenGL real, no en el hilo de interfaz de usuario.
Aparentemente, mi código para usar la textura ha sido correcto. Gracias por tu ayuda.
- Java.lang.RuntimeException: createWindowSurface falló EGL_BAD_ALLOC en android
- Estructura adecuada de una aplicación de Android con un cajón de navegación