2010-05-18 95 views
4

通过一些OpenGL-ES教程,使用Android模拟器。我已经开始使用纹理映射,并且在映射到多维数据集时遇到了一些问题。如下所述,是否可以将纹理映射到具有8个顶点和12个三角形的立方体的所有面上?OpenGL ES - 纹理映射8顶点立方体的所有面?

// Use half as we are going for a 0,0,0 centre. 
    width /= 2; 
    height /= 2; 
    depth /= 2; 

    float vertices[] = { -width, -height, depth, // 0 
          width, -height, depth, // 1 
          width, height, depth, // 2 
         -width, height, depth, // 3 
         -width, -height, -depth, // 4 
          width, -height, -depth, // 5 
          width, height, -depth, // 6 
         -width, height, -depth, // 7 
    }; 

    short indices[] = { 
      // Front 
      0,1,2, 
      0,2,3, 
      // Back 
      5,4,7, 
      5,7,6, 
      // Left 
      4,0,3, 
      4,3,7, 
      // Right 
      1,5,6, 
      1,6,2, 
      // Top 
      3,2,6, 
      3,6,7, 
      // Bottom 
      4,5,1, 
      4,1,0, 
    }; 

    float texCoords[] = { 
     1.0f, 1.0f, 
     0.0f, 1.0f, 
     0.0f, 0.0f, 
     1.0f, 0.0f, 

     1.0f, 1.0f, 
     0.0f, 1.0f, 
     0.0f, 0.0f, 
     1.0f, 0.0f, 

     1.0f, 1.0f, 
     0.0f, 1.0f, 
     0.0f, 0.0f, 
     1.0f, 0.0f, 

     1.0f, 1.0f, 
     0.0f, 1.0f, 
     0.0f, 0.0f, 
     1.0f, 0.0f, 

     1.0f, 1.0f, 
     0.0f, 1.0f, 
     0.0f, 0.0f, 
     1.0f, 0.0f, 

     1.0f, 1.0f, 
     0.0f, 1.0f, 
     0.0f, 0.0f, 
     1.0f, 0.0f, 
    }; 

我已经得到正面和背面正常工作,但是,没有其他面孔显示纹理。

alt text http://www.freeimagehosting.net/uploads/60d292613d.jpg

绘图代码

public void draw(GL10 gl) { 
    // Counter-clockwise winding. 
    gl.glFrontFace(GL10.GL_CCW); 

    // Enable face culling. 
    gl.glEnable(GL10.GL_CULL_FACE); 

    // What faces to remove with the face culling. 
    gl.glCullFace(GL10.GL_BACK); 

    // Enabled the vertices buffer for writing and to be used during 
    // rendering. 
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 

    // Specifies the location and data format of an array of vertex 
    // coordinates to use when rendering. 
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer); 

    if (normalsBuffer != null) { 
     // Enabled the normal buffer for writing and to be used during rendering. 
     gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); 

     // Specifies the location and data format of an array of normals to use when rendering. 
     gl.glNormalPointer(GL10.GL_FLOAT, 0, normalsBuffer); 
    } 

    // Set flat color 
    gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]); 

    // Smooth color 
    if (colorBuffer != null) { 
     // Enable the color array buffer to be used during rendering. 
     gl.glEnableClientState(GL10.GL_COLOR_ARRAY); 
     // Point out the where the color buffer is. 
     gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer); 
    } 

    // Use textures? 
    if (textureBuffer != null) { 
     gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
     gl.glEnable(GL10.GL_TEXTURE_2D); 
     gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); 
    } 

    // Translation and rotation before drawing 
    gl.glTranslatef(x, y, z); 
    gl.glRotatef(rx, 1, 0, 0); 
    gl.glRotatef(ry, 0, 1, 0); 
    gl.glRotatef(rz, 0, 0, 1); 

    gl.glDrawElements(GL10.GL_TRIANGLES, numOfIndices, GL10.GL_UNSIGNED_SHORT, indicesBuffer); 

    // Disable the vertices buffer. 
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
    gl.glDisableClientState(GL10.GL_COLOR_ARRAY); 
    gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); 
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 

    // Disable face culling. 
    gl.glDisable(GL10.GL_CULL_FACE); 
} 
+0

听起来像你可能会做每面的纹理而不是每个顶点的纹理。你可以发布更多的绘图代码,以便我们看到你如何将这些数据集合在一起? – jblocksom 2010-05-18 03:04:04

+0

我有一个例子,他们已经使用了24个顶点来定义他们的立方体。我相信这必须是每个顶点并且是默认的?我如何指定每个面? – Feet 2010-05-18 03:28:54

回答

6

你必须使用24个顶点。在OpenGL中,顶点不仅仅是位置,它是所有顶点属性的集合。每个顶点数组都使用相同的索引进行访问。

臭名昭着的魔方示例是几乎所有人在开始使用OpenGL时都觉得效率低下的问题,但在现实世界中,更复杂的模型中,复制程度相当低。

+0

你是什么意思,你必须使用24个顶点?如果您必须复制顶点,那么如果您仍然在向GPU发送重复数据,那么使用索引缓冲区的意义何在? – Matthew 2013-07-16 23:04:44

0

我也“只”修改GLES20TriangleRenderer.java文件到SDK例如BasicGLSurfaceView,编译它,测试它的两个Android设备中,Android手机和一台Nexus 7和两个设备这方面的工作不错:)

/* 
* Copyright (C) 2011 The Android Open Source Project 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
*  http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 

    Modified by YLP (06 January 2014) for to handle a rotated texture mapped cube 

*/ 

package com.example.android.basicglsurfaceview; 

import java.io.IOException; 
import java.io.InputStream; 
import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 

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

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.opengl.GLES20; 
import android.opengl.GLSurfaceView; 
import android.opengl.GLUtils; 
import android.opengl.Matrix; 
import android.os.SystemClock; 
import android.util.Log; 

class GLES20TriangleRenderer implements GLSurfaceView.Renderer { 

    public GLES20TriangleRenderer(Context context) { 
     mContext = context; 

     // mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
     // mTriangleVertices.put(mTriangleVerticesData).position(0); 

     mTriangleVertices = ByteBuffer.allocateDirect(cubeVerticesStrip.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
     mTriangleVertices.put(cubeVerticesStrip).position(0); 

     mTriangleTexcoords = ByteBuffer.allocateDirect(cubeTexCoordsStrip.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
     mTriangleTexcoords.put(cubeTexCoordsStrip).position(0); 

    } 

    public void onDrawFrame(GL10 glUnused) { 
     // Ignore the passed-in GL10 interface, and use the GLES20 
     // class's static methods instead. 
     GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f); 
     GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); 

     GLES20.glEnable(GLES20.GL_DEPTH_TEST); 
     GLES20.glDepthFunc(GLES20.GL_LEQUAL); 
     GLES20.glDepthMask(true); 

     GLES20.glUseProgram(mProgram); 
     checkGlError("glUseProgram"); 

     GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID); 

     // mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); 
     // GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 
     //  TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 
     // checkGlError("glVertexAttribPointer maPosition"); 

     // mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); 
     // GLES20.glEnableVertexAttribArray(maPositionHandle); 
     // checkGlError("glEnableVertexAttribArray maPositionHandle"); 

     // GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 
     //   TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 
     // checkGlError("glVertexAttribPointer maTextureHandle"); 
     // GLES20.glEnableVertexAttribArray(maTextureHandle); 
     // checkGlError("glEnableVertexAttribArray maTextureHandle"); 

     // From http://www.endodigital.com/opengl-es-2-0-on-the-iphone/part-fourteen-creating-the-cube 
     // (but slighty modified) 
     mTriangleVertices.position(0); 
     // GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 
      GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 0, mTriangleVertices); 
     GLES20.glEnableVertexAttribArray(maPositionHandle); 

     mTriangleTexcoords.position(0); 
     // GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 
      GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 0, mTriangleTexcoords); 
     GLES20.glEnableVertexAttribArray(maTextureHandle); 

     long time = SystemClock.uptimeMillis() % 4000L; 
     float angle = 0.090f * ((int) time); 
     float scale = 0.7f; 

     Matrix.setRotateM(mMMatrix, 0, angle, 0, 0, 1.0f); 

     // YLP : add others movements cycles 
     Matrix.rotateM(mMMatrix, 0, angle, 1.0f, 0.0f, 0.0f); 
     // Matrix.rotateM(mMMatrix, 0, angle, 0.0f, 1.0f, 0.0f); 
     // float scale = (float)(Math.abs(Math.sin(((float)time) * (6.28f/4000.0f)))); 
     Matrix.scaleM(mMMatrix, 0, scale, scale, scale); 


     Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0); 
     Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0); 

     GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); 

     // Somes tests with only somes triangles 
     // GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); // worked initialy but only one triangle 
     // GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6); // worked initialy but only two triangles 
     // GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); // GL_QUADS does not exist in GL 2.0 :(
     // GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 8); // GL_QUADS does not exist in GL 2.0 :(

     // Draw the cube 
     // TODO : make only one glDraWArrays() call instead one per face 
     GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 
     GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 4, 4); 
     GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 8, 4); 
     GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 12, 4); 
     GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 16, 4); 
     GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 20, 4); 

     checkGlError("glDrawArrays"); 
    } 

    public void onSurfaceChanged(GL10 glUnused, int width, int height) { 
     // Ignore the passed-in GL10 interface, and use the GLES20 
     // class's static methods instead. 
     GLES20.glViewport(0, 0, width, height); 
     float ratio = (float) width/height; 
     Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); 
    } 

    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) { 
     // Ignore the passed-in GL10 interface, and use the GLES20 
     // class's static methods instead. 
     mProgram = createProgram(mVertexShader, mFragmentShader); 
     if (mProgram == 0) { 
      return; 
     } 
     maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition"); 
     checkGlError("glGetAttribLocation aPosition"); 
     if (maPositionHandle == -1) { 
      throw new RuntimeException("Could not get attrib location for aPosition"); 
     } 
     maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord"); 
     checkGlError("glGetAttribLocation aTextureCoord"); 
     if (maTextureHandle == -1) { 
      throw new RuntimeException("Could not get attrib location for aTextureCoord"); 
     } 

     muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 
     checkGlError("glGetUniformLocation uMVPMatrix"); 
     if (muMVPMatrixHandle == -1) { 
      throw new RuntimeException("Could not get attrib location for uMVPMatrix"); 
     } 

     /* 
     * Create our texture. This has to be done each time the 
     * surface is created. 
     */ 

     int[] textures = new int[1]; 
     GLES20.glGenTextures(1, textures, 0); 

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

     GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, 
       GLES20.GL_NEAREST); 
     GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, 
       GLES20.GL_TEXTURE_MAG_FILTER, 
       GLES20.GL_LINEAR); 

     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, 
       GLES20.GL_REPEAT); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, 
       GLES20.GL_REPEAT); 

     InputStream is = mContext.getResources() 
      .openRawResource(R.raw.robot); 
     Bitmap bitmap; 
     try { 
      bitmap = BitmapFactory.decodeStream(is); 
     } finally { 
      try { 
       is.close(); 
      } catch(IOException e) { 
       // Ignore. 
      } 
     } 

     GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 
     bitmap.recycle(); 

     Matrix.setLookAtM(mVMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 
    } 

    private int loadShader(int shaderType, String source) { 
     int shader = GLES20.glCreateShader(shaderType); 
     if (shader != 0) { 
      GLES20.glShaderSource(shader, source); 
      GLES20.glCompileShader(shader); 
      int[] compiled = new int[1]; 
      GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); 
      if (compiled[0] == 0) { 
       Log.e(TAG, "Could not compile shader " + shaderType + ":"); 
       Log.e(TAG, GLES20.glGetShaderInfoLog(shader)); 
       GLES20.glDeleteShader(shader); 
       shader = 0; 
      } 
     } 
     return shader; 
    } 

    private int createProgram(String vertexSource, String fragmentSource) { 
     int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); 
     if (vertexShader == 0) { 
      return 0; 
     } 

     int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); 
     if (pixelShader == 0) { 
      return 0; 
     } 

     int program = GLES20.glCreateProgram(); 
     if (program != 0) { 
      GLES20.glAttachShader(program, vertexShader); 
      checkGlError("glAttachShader"); 
      GLES20.glAttachShader(program, pixelShader); 
      checkGlError("glAttachShader"); 
      GLES20.glLinkProgram(program); 
      int[] linkStatus = new int[1]; 
      GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); 
      if (linkStatus[0] != GLES20.GL_TRUE) { 
       Log.e(TAG, "Could not link program: "); 
       Log.e(TAG, GLES20.glGetProgramInfoLog(program)); 
       GLES20.glDeleteProgram(program); 
       program = 0; 
      } 
     } 
     return program; 
    } 

    private void checkGlError(String op) { 
     int error; 
     while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { 
      Log.e(TAG, op + ": glError " + error); 
      throw new RuntimeException(op + ": glError " + error); 
     } 
    } 

    private static final int FLOAT_SIZE_BYTES = 4; 
    private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; 
    private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; 
    private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; 
    private static final int TRIANGLE_TEXCOORDS_DATA_STRIDE_BYTES = 2 * FLOAT_SIZE_BYTES; 

    private final float[] mTriangleVerticesData = 
    { 
      // X, Y, Z, U, V 

      // initial triangle from the source 
      // -1.0f, -0.5f,   0, -0.5f, 0.0f, 
      // 1.0f, -0.5f,   0, 1.5f, -0.0f, 
      // 0.0f, 1.11803399f, 0, 0.5f, 1.61803399f, 

      // YLP : transform this to two triangles for to have a quad 
      // -1, -1, 0, 0, 0, 
      // 1, -1, 0, 1, 0, 
      // -1, 1, 0, 0, 1, 
      // 1, 1, 0, 1, 1, 
      // -1, 1, 0, 0, 1, 
      // 1, -1, 0, 1, 0 

      // YLP : use two quads with GL_TRIANGLE_STRIP 
      // Don't work because this make one accordeon effect :(
      -1, -1, -1, 0, 0, 
      1, -1, -1, 1, 0, 
      -1, 1, -1, 0, 1, 
      1, 1, -1, 1, 1, 
      -1, -1, 1, 0, 0, 
      1, -1, 1, 1, 0, 
      -1, 1, 1, 0, 1, 
      1, 1, 1, 1, 1, 
    }; 

    // From http://www.endodigital.com/opengl-es-2-0-on-the-iphone/part-fourteen-creating-the-cube/ 
    // (only moodify "static const GLfloat" to "private final float" on it) 
    private final float cubeVerticesStrip[] = { 
      // Front face 
      -1,-1,1, 1,-1,1, -1,1,1, 1,1,1, 
      // Right face 
      1,-1,1, 1,-1,-1, 1,1,1, 1,1,-1, 
      // Back face 
      1,-1,-1, -1,-1,-1, 1,1,-1, -1,1,-1, 
      // Left face 
      -1,-1,-1, -1,-1,1, -1,1,-1, -1,1,1, 
      // Bottom face 
      -1,-1,-1, 1,-1,-1, -1,-1,1, 1,-1,1, 
      // Top face 
      -1,1,1, 1,1,1, -1,1,-1, 1,1,-1 

    }; 

    private final float cubeTexCoordsStrip[] = { 
      // Front face 
      0,0, 1,0, 0,1, 1,1, 
      // Right face 
      0,0, 1,0, 0,1, 1,1, 
      // Back face 
      0,0, 1,0, 0,1, 1,1, 
      // Left face 
      0,0, 1,0, 0,1, 1,1, 
      // Bottom face 
      0,0, 1,0, 0,1, 1,1, 
      // Top face 
      0,0, 1,0, 0,1, 1,1 
    }; 

    private FloatBuffer mTriangleVertices; 
    private FloatBuffer mTriangleTexcoords; 

    private final String mVertexShader = 
     "uniform mat4 uMVPMatrix;\n" + 
     "attribute vec4 aPosition;\n" + 
     "attribute vec2 aTextureCoord;\n" + 
     "varying vec2 vTextureCoord;\n" + 
     "void main() {\n" + 
     " gl_Position = uMVPMatrix * aPosition;\n" + 
     " vTextureCoord = aTextureCoord;\n" + 
     "}\n"; 

    private final String mFragmentShader = 
     "precision mediump float;\n" + 
     "varying vec2 vTextureCoord;\n" + 
     "uniform sampler2D sTexture;\n" + 
     "void main() {\n" + 
     " gl_FragColor = texture2D(sTexture, vTextureCoord);\n" + 
     "}\n"; 

    private float[] mMVPMatrix = new float[16]; 
    private float[] mProjMatrix = new float[16]; 
    private float[] mMMatrix = new float[16]; 
    private float[] mVMatrix = new float[16]; 

    private float[] mMMatrix2 = new float[16]; 

    private int mProgram; 
    private int mTextureID; 
    private int muMVPMatrixHandle; 
    private int maPositionHandle; 
    private int maTextureHandle; 

    private Context mContext; 
    private static String TAG = "GLES20TriangleRenderer"; 
} 

=>我设法在短短几个小时来实现这一点,这项工作:)

==>因此,如果Android是不是最好的平台,这似乎但是一个很好的和可行的。平台的我开始玩一些Android设备上的multimédia开发:)