开发者

How to texture glDrawElements

I have no Idea how I would texture something drawn by using glDrawElements? From what I gather you need to use glTexCoordPointer? but I'm still really confused.

I'll put the whole program here so you can see what I'm doing

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

Any help or advise would help I'm just confused ?


Ya this is the array buffer

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

I can add the whole program if you'd like to see?


As you have created (I hope) a GL_ARRAY_BUFFER with your vertices and set it with glVertexPointer, you should create a GL_ARRAY_BUFFER with your texture coordinates and set it using glTexCoordPointer. Could you copy paste your glVertexPointer call?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜