renderer.java

来自「NeHe用java与OpenGL结合教程源码」· Java 代码 · 共 465 行 · 第 1/2 页

JAVA
465
字号
package demos.nehe.lesson36;

import com.sun.opengl.util.BufferUtil;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.DebugGL;
import javax.media.opengl.glu.GLU;
import java.nio.ByteBuffer;

import demos.common.GLDisplay;

class Renderer implements GLEventListener {
    private int TEXTURE_SIZE = 128;

    private static final int x = 0;                                        // Define X Coord
    private static final int y = 1;                                        // Define Y Coord
    private static final int z = 2;                                        // Define Z Coord

// User Defined Variables
    private float angle; // Used To Rotate The Helix
    private float[][] vertexes = new float[4][3]; // Holds Float Info For 4 Sets Of Vertices
    private float[] normal = new float[3]; // An Array To Store The Normal Data
    private int blurTexture; // An Unsigned Int To Store The Texture Number
    private long previousTime = System.currentTimeMillis();

    private GLU glu = new GLU();

    private int frameBufferObject;
    private GLDisplay display;

    public Renderer(GLDisplay display) {
        this.display = display;
    }

    private int createBlurTexture(GL gl) {                                // Create An Empty Texture
        ByteBuffer data = BufferUtil.newByteBuffer(TEXTURE_SIZE * TEXTURE_SIZE); // Create Storage Space For Texture Data (128x128x4)
        data.limit(data.capacity());

        int[] txtnumber = new int[1];
        gl.glGenTextures(1, txtnumber, 0);                                // Create 1 Texture
        gl.glBindTexture(GL.GL_TEXTURE_2D, txtnumber[0]);                 // Bind The Texture
        gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_LUMINANCE, TEXTURE_SIZE, TEXTURE_SIZE, 0, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE, data);                        // Build Texture Using Information In data
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);

        return txtnumber[0];                                              // Return The Texture ID
    }

    private void normalize(float[] vector) {                             // Normalizes A Vector (3 Coordinates)
        // To A Unit Normal Vector With A Length Of One.
        // Calculates The Length Of The Vector
        float length = (float) Math.sqrt((vector[0] * vector[0]) + (vector[1] * vector[1]) + (vector[2] * vector[2]));

        if (length == 0.0f)                                               // Prevents Divide By 0 Error By Providing
        {
            length = 1.0f;                                                // An Acceptable Value For Vectors To Close To 0.
        }

        vector[0] /= length;                                              // Dividing Each Element By
        vector[1] /= length;                                              // The Length Results In A
        vector[2] /= length;                                              // Unit Normal Vector.
    }

    private void calcNormal(float[][] v/*[3][3]*/, float[] out/*[3]*/) {  // Calculates Normal For A Quad Using 3 Points
        float[] v1 = new float[3];
        float[] v2 = new float[3];                                        // Vector 1 (x,y,z) & Vector 2 (x,y,z)

        // Finds The Vector Between 2 Points By Subtracting
        // The x,y,z Coordinates From One Point To Another.

        // Calculate The Vector From Point 1 To Point 0
        v1[x] = v[0][x] - v[1][x];                                        // Vector 1.x=Vertex[0].x-Vertex[1].x
        v1[y] = v[0][y] - v[1][y];                                        // Vector 1.y=Vertex[0].y-Vertex[1].y
        v1[z] = v[0][z] - v[1][z];                                        // Vector 1.z=Vertex[0].y-Vertex[1].z
        // Calculate The Vector From Point 2 To Point 1
        v2[x] = v[1][x] - v[2][x];                                        // Vector 2.x=Vertex[0].x-Vertex[1].x
        v2[y] = v[1][y] - v[2][y];                                        // Vector 2.y=Vertex[0].y-Vertex[1].y
        v2[z] = v[1][z] - v[2][z];                                        // Vector 2.z=Vertex[0].z-Vertex[1].z
        // Compute The Cross Product To Give Us A Surface Normal
        out[x] = v1[y] * v2[z] - v1[z] * v2[y];                           // Cross Product For Y - Z
        out[y] = v1[z] * v2[x] - v1[x] * v2[z];                           // Cross Product For X - Z
        out[z] = v1[x] * v2[y] - v1[y] * v2[x];                           // Cross Product For X - Y

        normalize(out);                                                // Normalize The Vectors
    }

    private void processHelix(GL gl, GLU glu) {                           // Draws A Helix
        float x;                                                          // Helix x Coordinate
        float y;                                                          // Helix y Coordinate
        float z;                                                          // Helix z Coordinate
        float phi;                                                        // Angle
        float theta;                                                      // Angle
        float v, u;                                                       // Angles
        float r;                                                          // Radius Of Twist
        int twists = 5;                                                   // 5 Twists

        float[] glfMaterialColor = new float[]{0.4f, 0.2f, 0.8f, 1.0f};  // Set The Material Color
        float[] specular = new float[]{1.0f, 1.0f, 1.0f, 1.0f};          // Sets Up Specular Lighting

        gl.glLoadIdentity();                                             // Reset The Modelview Matrix
        glu.gluLookAt(0, 5, 50, 0, 0, 0, 0, 1, 0);                       // Eye Position (0,5,50) Center Of Scene (0,0,0), Up On Y Axis

        gl.glPushMatrix();                                               // Push The Modelview Matrix

        gl.glTranslatef(0, 0, -50);                                      // Translate 50 Units Into The Screen
        gl.glRotatef(angle / 2.0f, 1, 0, 0);                             // Rotate By angle/2 On The X-Axis
        gl.glRotatef(angle / 3.0f, 0, 1, 0);                             // Rotate By angle/3 On The Y-Axis

        gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE, glfMaterialColor, 0);
        gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, specular, 0);

        r = 1.5f;                                                        // Radius

        gl.glBegin(GL.GL_QUADS);                                         // Begin Drawing Quads
        for (phi = 0; phi <= 360; phi += 20.0)                           // 360 Degrees In Steps Of 20
        {
            for (theta = 0; theta <= 360 * twists; theta += 20.0)        // 360 Degrees * Number Of Twists In Steps Of 20
            {
                v = (phi / 180.0f * 3.142f);                             // Calculate Angle Of First Point	(  0 )
                u = (theta / 180.0f * 3.142f);                           // Calculate Angle Of First Point	(  0 )

                x = (float) (Math.cos(u) * (2.0f + Math.cos(v))) * r;    // Calculate x Position (1st Point)
                y = (float) (Math.sin(u) * (2.0f + Math.cos(v))) * r;    // Calculate y Position (1st Point)
                z = (float) (((u - (2.0f * 3.142f)) + Math.sin(v)) * r); // Calculate z Position (1st Point)

                vertexes[0][0] = x;                                      // Set x Value Of First Vertex
                vertexes[0][1] = y;                                      // Set y Value Of First Vertex
                vertexes[0][2] = z;                                      // Set z Value Of First Vertex

                v = (phi / 180.0f * 3.142f);                             // Calculate Angle Of Second Point	(  0 )
                u = ((theta + 20) / 180.0f * 3.142f);                    // Calculate Angle Of Second Point	( 20 )

                x = (float) (Math.cos(u) * (2.0f + Math.cos(v))) * r;    // Calculate x Position (2nd Point)
                y = (float) (Math.sin(u) * (2.0f + Math.cos(v))) * r;    // Calculate y Position (2nd Point)
                z = (float) (((u - (2.0f * 3.142f)) + Math.sin(v)) * r); // Calculate z Position (2nd Point)

                vertexes[1][0] = x;                                      // Set x Value Of Second Vertex
                vertexes[1][1] = y;                                      // Set y Value Of Second Vertex
                vertexes[1][2] = z;                                      // Set z Value Of Second Vertex

                v = ((phi + 20) / 180.0f * 3.142f);                      // Calculate Angle Of Third Point	( 20 )
                u = ((theta + 20) / 180.0f * 3.142f);                    // Calculate Angle Of Third Point	( 20 )

                x = (float) (Math.cos(u) * (2.0f + Math.cos(v))) * r;    // Calculate x Position (3rd Point)
                y = (float) (Math.sin(u) * (2.0f + Math.cos(v))) * r;    // Calculate y Position (3rd Point)
                z = (float) (((u - (2.0f * 3.142f)) + Math.sin(v)) * r); // Calculate z Position (3rd Point)

                vertexes[2][0] = x;                                      // Set x Value Of Third Vertex
                vertexes[2][1] = y;                                      // Set y Value Of Third Vertex
                vertexes[2][2] = z;                                      // Set z Value Of Third Vertex

                v = ((phi + 20) / 180.0f * 3.142f);                      // Calculate Angle Of Fourth Point	( 20 )
                u = ((theta) / 180.0f * 3.142f);                         // Calculate Angle Of Fourth Point	(  0 )

                x = (float) (Math.cos(u) * (2.0f + Math.cos(v))) * r;    // Calculate x Position (4th Point)
                y = (float) (Math.sin(u) * (2.0f + Math.cos(v))) * r;    // Calculate y Position (4th Point)
                z = (float) (((u - (2.0f * 3.142f)) + Math.sin(v)) * r); // Calculate z Position (4th Point)

                vertexes[3][0] = x;                                      // Set x Value Of Fourth Vertex
                vertexes[3][1] = y;                                      // Set y Value Of Fourth Vertex
                vertexes[3][2] = z;                                      // Set z Value Of Fourth Vertex

                calcNormal(vertexes, normal);                            // Calculate The Quad Normal

                gl.glNormal3f(normal[0], normal[1], normal[2]);          // Set The Normal

                // Render The Quad
                gl.glVertex3f(vertexes[0][0], vertexes[0][1], vertexes[0][2]);
                gl.glVertex3f(vertexes[1][0], vertexes[1][1], vertexes[1][2]);
                gl.glVertex3f(vertexes[2][0], vertexes[2][1], vertexes[2][2]);
                gl.glVertex3f(vertexes[3][0], vertexes[3][1], vertexes[3][2]);
            }
        }
        gl.glEnd();                                                      // Done Rendering Quads

        gl.glPopMatrix();                                                // Pop The Matrix
    }

    private void viewOrtho(GL gl)                                        // Set Up An Ortho View
    {
        gl.glMatrixMode(GL.GL_PROJECTION);                               // Select Projection
        gl.glPushMatrix();                                               // Push The Matrix
        gl.glLoadIdentity();                                             // Reset The Matrix
        gl.glOrtho(0, 640, 480, 0, -1, 1);                               // Select Ortho Mode (640x480)
        gl.glMatrixMode(GL.GL_MODELVIEW);                                // Select Modelview Matrix
        gl.glPushMatrix();                                               // Push The Matrix
        gl.glLoadIdentity();                                             // Reset The Matrix
    }

    private void viewPerspective(GL gl)                                  // Set Up A Perspective View
    {
        gl.glMatrixMode(GL.GL_PROJECTION);                               // Select Projection
        gl.glPopMatrix();                                                // Pop The Matrix
        gl.glMatrixMode(GL.GL_MODELVIEW);                                // Select Modelview
        gl.glPopMatrix();                                                // Pop The Matrix
    }

    /**
     * Renders To A Texture
     */
    private void renderToTexture(GL gl, GLU glu)
    {
        if (frameBufferObject != -1) {
            // Bind the fbo
            gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBufferObject);
        }

        // Set Our Viewport (Match Texture Size)
        gl.glViewport(0, 0, TEXTURE_SIZE, TEXTURE_SIZE);

        // Clear the frame buffer (either the default frame buffer or the fbo)
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

        // Render The Helix
        processHelix(gl, glu);

        // Copy Our ViewPort To The Blur Texture (From 0,0 To 128,128... No Border)
        gl.glBindTexture(GL.GL_TEXTURE_2D, blurTexture);
        gl.glCopyTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_LUMINANCE, 0, 0, TEXTURE_SIZE, TEXTURE_SIZE, 0);

        if (frameBufferObject != -1) {
            // If we used the fbo, restore the default frame buffer
            gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
        }

        // Restore the viewport (0,0 to 640x480)
        gl.glViewport(0, 0, 640, 480);
    }

    private void drawBlur(GL gl, int times, float inc)           // Draw The Blurred Image

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?