2011-01-14 3 views
0

У меня нет идеи, как бы я текстурировал что-то нарисованное с помощью glDrawElements? Из того, что я собираюсь, вам нужно использовать glTexCoordPointer? но я все еще очень смущен.Как текстура glDrawElements

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

public class DrawWater { 

    public Expr2 func; // The function that is being drawn. 
    private String functionInput; 
    private boolean version_1_5; // Check is OpenGL 1.5 is available; set in init(). 
    public boolean dataIsValid; // Set to true whenever data needs to be recomputed. 
    public double xMax = 5; 
    public double yMax = 5; 
    private int[] textures = new int[3];   // Storage For 3 Textures 
    // This is checked in the display() method before drawing. 
    /* Buffers to hold the points and normals for the surface. */ 
    private FloatBuffer vBuf = BufferUtil.newFloatBuffer(201 * 201 * 3); 
    private FloatBuffer nBuf = BufferUtil.newFloatBuffer(201 * 201 * 3); 

    /* Buffers to hold the indices for drawing the surface and lines with glDrawElements*/ 
    private IntBuffer surfaceIndexBuffer = BufferUtil.newIntBuffer(200 * 201 * 2); 
    private IntBuffer xLineIndexBuffer = BufferUtil.newIntBuffer(21 * 201); 
    private IntBuffer yLineIndexBuffer = BufferUtil.newIntBuffer(21 * 201); 

    /* VBO ID numbers for holding the data when OpenGL version is 1.5 or higher */ 
    private int vertexVBO, normalVBO;   // VBO IDs for surface data. 
    private int xLineVBO, yLineVBO, surfaceVBO; // VBO IDs for index data. 

    public DrawWater() { 
    } 

    public void setup(GL gl, String equ) { 

     this.functionInput = equ; 
     this.func = new Expr2(equ); 
    } 

    public void draw(GL gl) { 

     version_1_5 = gl.isExtensionAvailable("GL_VERSION_1_5"); 

     if (gl.isExtensionAvailable("GL_VERSION_1_3")) { 
      gl.glEnable(GL.GL_MULTISAMPLE); 
     } 

     makeElementBuffers(); // Generate lists of indices for glDrawElements. This data never changes. 

     if (version_1_5) { 
      // Generate VBOs for the data, and fill the ones that are for index data with 
      // data from Java nio buffers. The VBOs for index data won't change again and 
      // so use GL.GL_STATIC_DRAW. 
      int[] ids = new int[5]; 
      gl.glGenBuffers(5, ids, 0); 

      this.vertexVBO = ids[0]; 
      this.normalVBO = ids[1]; 
      this.xLineVBO = ids[2]; 
      this.yLineVBO = ids[3]; 
      this.surfaceVBO = ids[4]; 

      gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexVBO); 
      gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0); 
      gl.glBindBuffer(GL.GL_ARRAY_BUFFER, normalVBO); 
      gl.glNormalPointer(GL.GL_FLOAT, 0, 0); 
      gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); 
      gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, surfaceVBO); 
      gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, 4 * 2 * 200 * 201, surfaceIndexBuffer, GL.GL_STATIC_DRAW); 
      gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, xLineVBO); 
      gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, 4 * 21 * 201, xLineIndexBuffer, GL.GL_STATIC_DRAW); 
      gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, yLineVBO); 
      gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, 4 * 21 * 201, yLineIndexBuffer, GL.GL_STATIC_DRAW); 
      gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0); 

     } else { 

      gl.glVertexPointer(3, GL.GL_FLOAT, 0, vBuf); 
      gl.glNormalPointer(GL.GL_FLOAT, 0, nBuf); 

     } 



     this.dataIsValid = false; // Force recomputation of data with new graph definition. 

     if (func != null) { 

      gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, new float[]{0.7f, 0.7f, 1}, 0); 
      gl.glMaterialfv(GL.GL_BACK, GL.GL_AMBIENT_AND_DIFFUSE, new float[]{0.8f, 0.8f, 0.5f}, 0); 

      if (!dataIsValid) { 
       this.computeSurfaceData(); 
       if (version_1_5) { 
        // Set up VBOs for surface points and normals. Since these change 
        // pretty regularly, use GL.GL_DYNAMIC_DRAW. 
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexVBO); 
        gl.glBufferData(GL.GL_ARRAY_BUFFER, 4 * 3 * 201 * 201, vBuf, GL.GL_DYNAMIC_DRAW); 
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, normalVBO); 
        gl.glBufferData(GL.GL_ARRAY_BUFFER, 4 * 3 * 201 * 201, nBuf, GL.GL_DYNAMIC_DRAW); 
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); 
       } 
      } 
      gl.glEnableClientState(GL.GL_VERTEX_ARRAY); 
      gl.glEnableClientState(GL.GL_NORMAL_ARRAY); 

      this.drawSurface(gl); // Just draw the surface. 

      gl.glPolygonOffset(1, 1); 
      gl.glEnable(GL.GL_POLYGON_OFFSET_FILL); 

      this.drawSurface(gl); 

      gl.glDisable(GL.GL_POLYGON_OFFSET_FILL); 
      gl.glDisable(GL.GL_LIGHTING); 
      gl.glColor3f(0, 0, 0); 
      gl.glDisableClientState(GL.GL_NORMAL_ARRAY); 

      gl.glEnable(GL.GL_LIGHTING); 
     } 
     gl.glDisableClientState(GL.GL_VERTEX_ARRAY); 
     gl.glDisableClientState(GL.GL_NORMAL_ARRAY); 


    } 



    private void makeElementBuffers() { 
     for (int i = 0; i < 201; i += 10) { // indices for drawing lines in x-direction 
      for (int j = 0; j < 201; j++) { 
       this.xLineIndexBuffer.put(201 * i + j); 
      } 
     } 
     for (int i = 0; i < 201; i += 10) { // indices for drawing lines in y-direction 
      for (int j = 0; j < 201; j++) { 
       this.yLineIndexBuffer.put(201 * j + i); 
      } 
     } 
     for (int i = 0; i < 200; i++) { // indices for drawing surface with GL_TRIANGLE_STRIPs 
      for (int j = 0; j < 201; j++) { 
       this.surfaceIndexBuffer.put(201 * (i + 1) + j); 
       this.surfaceIndexBuffer.put(201 * i + j); 
      } 
     } 
     this.xLineIndexBuffer.rewind(); 
     this.yLineIndexBuffer.rewind(); 
     this.surfaceIndexBuffer.rewind(); 
    } 

    private void computeSurfaceData() { 
     double xmin = -xMax; 
     double xmax = xMax; 
     double ymin = -yMax; 
     double ymax = yMax; 
     double xRes = 200; 
     double yRes = 200; 
     float[] surfaceData = new float[301 * 3]; 
     float[] normalData = new float[301 * 3]; 
     double dx = (xmax - xmin)/xRes; 
     double dy = (ymax - ymin)/yRes; 

     for (int i = 0; i <= xRes; i++) { 
      int v = 0; 
      int n = 0; 
      double y1 = ymin + dy * i; 

      for (int j = 0; j <= yRes; j++) { 
       double x = xmin + dx * j; 
       func.setVariable('x', x); 
       func.setVariable('y', y1); 
       double z1 = func.value(); 
       float[] normal1 = computeUnitNormal(x, y1); 
       surfaceData[v++] = (float) x; 
       surfaceData[v++] = (float) y1; 
       surfaceData[v++] = (float) z1; 
       normalData[n++] = normal1[0]; 
       normalData[n++] = normal1[1]; 
       normalData[n++] = normal1[2]; 
      } 
      vBuf.put(surfaceData, 0, 201 * 3); 
      nBuf.put(normalData, 0, 201 * 3); 
     } 
     vBuf.rewind(); 
     nBuf.rewind(); 
     dataIsValid = true; 
    } 

    /** 
    * Draw the surface as a series of triangle strips. 
    */ 
    private void drawSurface(GL gl) { 


     if (version_1_5) { 
      gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, surfaceVBO); 
      for (int i = 0; i < 200; i++) { 
       gl.glTexCoordPointer(3, GL.GL_TRIANGLE_STRIP, 402, nBuf); 
       gl.glDrawElements(GL.GL_TRIANGLE_STRIP, 402, GL.GL_UNSIGNED_INT, 402 * i * 4); 
      } 
      gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0); 
     } else { 
      for (int i = 0; i < 200; i++) { 
       surfaceIndexBuffer.position(402 * i); 
       gl.glDrawElements(GL.GL_TRIANGLE_STRIP, 402, GL.GL_UNSIGNED_INT, surfaceIndexBuffer); 
      } 
     } 
    } 

    /** 
    * Compute a unit normal to the graph of z = func(x,y). 
    * This is only an approximation, using nearby points instead 
    * of exact derivatives. 
    */ 
    private float[] computeUnitNormal(double x, double y) { 
     double epsilon = 0.00001; 
     func.setVariable('x', x); 
     func.setVariable('y', y); 
     double z = this.func.value(); 
     func.setVariable('x', x + epsilon); 
     double z1 = func.value(); 
     func.setVariable('x', x); 
     func.setVariable('y', y + epsilon); 
     double z2 = this.func.value(); 
     // normal is (epsilon,0,z1-z) X (0,epsilon,z2-z) 
     double a = -epsilon * (z1 - z); 
     double b = -epsilon * (z2 - z); 
     double c = epsilon * epsilon; 
     double length = Math.sqrt(a * a + b * b + c * c); 

     if (Double.isNaN(length) || Double.isInfinite(length)) { 
      return new float[]{0, 0, 1}; 
     } else { 
      return new float[]{(float) (a/length), (float) (b/length), (float) (c/length)}; 
     } 

    } 

    private void loadGLTextures(GLAutoDrawable gldrawable) throws IOException { 
     TextureReader.Texture texture = null; 
     texture = TextureReader.readTexture("data/images/04.bmp"); 

     GL gl = gldrawable.getGL(); 

     //Create Nearest Filtered Texture 
     gl.glGenTextures(1, textures, 0); 
     gl.glBindTexture(GL.GL_TEXTURE_2D, textures[0]); 

     gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); 
     gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); 

     gl.glTexImage2D(GL.GL_TEXTURE_2D, 
       0, 
       3, 
       texture.getWidth(), 
       texture.getHeight(), 
       0, 
       GL.GL_RGB, 
       GL.GL_UNSIGNED_BYTE, 
       texture.getPixels()); 
    } 
} 

Любая помощь или посоветовать бы помочь, я просто путать?


Я это буфер массив

int[] ids = new int[5]; 
      gl.glGenBuffers(5, ids, 0); 

      this.vertexVBO = ids[0]; 
      this.normalVBO = ids[1]; 
      this.xLineVBO = ids[2]; 
      this.yLineVBO = ids[3]; 
      this.surfaceVBO = ids[4]; 

      gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexVBO); 
      gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0); 
      gl.glBindBuffer(GL.GL_ARRAY_BUFFER, normalVBO); 
      gl.glNormalPointer(GL.GL_FLOAT, 0, 0); 
      gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); 
      gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, surfaceVBO); 
      gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, 4 * 2 * 200 * 201, surfaceIndexBuffer, GL.GL_STATIC_DRAW); 
      gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, xLineVBO); 
      gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, 4 * 21 * 201, xLineIndexBuffer, GL.GL_STATIC_DRAW); 
      gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, yLineVBO); 
      gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, 4 * 21 * 201, yLineIndexBuffer, GL.GL_STATIC_DRAW); 

Я могу добавить всю программу, если вы хотели бы видеть?

+0

Пожалуйста, не забудьте указать целевую версию OpenGL в вопросе. – Kos

ответ

1

Как вы создали (я надеюсь) а GL_ARRAY_BUFFER с вершинами и установить его с glVertexPointer, вы должны создать GL_ARRAY_BUFFER с текстурными координатами и установить его с помощью glTexCoordPointer. Не могли бы вы скопировать вставку вашего вызова glVertexPointer?

Смежные вопросы