OpenGL ES 2.0 – Текстуры всегда черные

Сегодня я читал много о текстурах в Open GL ES 2.0. Моя проблема в том, что все они черные.

Мой код:

Чтобы создать текстуру из растрового изображения:

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(); } 

В моем логарифме нет ошибок, похоже, похоже, что это так.

Как я использую текстуру:

  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 говорит что-то вроде этого:

 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 

Значит, нет ошибки, похоже, работает?

Мои шейдеры:

Фрагментный шейдер:

 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; } 

Похоже, что текстура2D возвращает нулевой вектор в шейдере фрагмента, так как если я просто напишу gl_FragColor = vec4(0.5,0.5,0.5,1.0) + texture2D(..) он будет нарисован.

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

Я уже уменьшил масштаб текстуры до 512×512, затем 256×256 и даже ниже до 64×64, но никаких изменений. Я распечатал свои обработчики текстур, проверил на ошибки GL и т. Д., Но ничего.

РЕДАКТИРОВАТЬ:

Сначала я пытаюсь загрузить текстуру с R.raw, а затем переместил ее в R.drawable, но никаких изменений.

EDIT 2: вершины куба / нормали / текстура / цвет:

 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 }; 

РЕДАКТИРОВАТЬ 3: Координаты текстуры как Цвета, чтобы увидеть, передаются ли они:

gl_FragColor = vec4(v_TexCoordinate.x, v_TexCoordinate.y, 0, 1); В шейдере фрагмента получается:

Введите описание изображения здесь

Это очень распространенная проблема, тогда вы не работаете с мощью 2 текстур (пиксель мудрый).

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

Android OpenGL2.0 показывает черные текстуры

Надеюсь, это решит вашу проблему.

Приветствие Маурицио

Хорошо, я нашел решение. Я снова был смущен тем, как работает поток OpenGL. Я загружал Bitmap в поток, а затем использовал glView.post(); Чтобы опубликовать Runnable обратно в (как я думал) поток OpenGL, где текстура должна была быть сгенерирована и привязана к растровому изображению.

Это не работает. Я должен был сделать следующее:

 GLSurfaceView glView = ...; glView.queueEvent(new Runnable() { @Override public void run() { generateTexture(bitmap); } }); 

Где в generateTexture, я выполняю все GLES20.generateTexture т. Д., Поскольку с queueEvent он снова находится в реальном потоке OpenGL, а не в потоке пользовательского интерфейса.

По-видимому, мой код для использования текстуры был правильным. Спасибо за вашу помощь.