📄 renderer.java
字号:
package demos.nehe.lesson26;
import demos.common.TextureReader;
import javax.media.opengl.*;
import javax.media.opengl.glu.GLUquadric;
import javax.media.opengl.glu.GLU;
import java.io.IOException;
class Renderer implements GLEventListener {
private float xrot = 0f; // X Rotation
private float yrot = 0f; // Y Rotation
private float xspeed = 0f; // X Rotation Speed
private boolean increaseXspeed;
private boolean decreaseXspeed;
private float yspeed = 0f; // Y Rotation Speed
private boolean increaseYspeed;
private boolean decreaseYspeed;
private float zoom = -7.0f; // Depth Into The Screen
private boolean zoomIn;
private boolean zoomOut;
private float height = 2.0f; // Height Of Ball From Floor
private boolean increaseHeight;
private boolean decreaseHeight;
private int textures[] = new int[3]; // Storage For 6 Textures (Modified)
private float lightAmbient[] = {0.2f, 0.2f, 0.2f}; // Ambient Light is 20% white
private float lightDiffuse[] = {1.0f, 1.0f, 1.0f}; // Diffuse Light is white
private float lightPosition[] = {0.0f, 0.0f, 2.0f}; // Position is somewhat in front of screen
private GLUquadric q; // Storage For Our Quadratic Objects
private GLU glu = new GLU();
public Renderer() {
}
public float getZoom() {
return zoom;
}
public void zoomIn(boolean zoom) {
zoomIn = zoom;
}
public void zoomOut(boolean zoom) {
zoomOut = zoom;
}
public void increaseHeight(boolean increase) {
increaseHeight = increase;
}
public void decreaseHeight(boolean decrease) {
decreaseHeight = decrease;
}
public void increaseXspeed(boolean increase) {
increaseXspeed = increase;
}
public void decreaseXspeed(boolean decrease) {
decreaseXspeed = decrease;
}
public void increaseYspeed(boolean increase) {
increaseYspeed = increase;
}
public void decreaseYspeed(boolean decrease) {
decreaseYspeed = decrease;
}
public void loadGLTextures(GL gl) throws IOException {
String[] textureNames = new String[]{
"demos/data/images/envwall.jpg",
"demos/data/images/ball.jpg",
"demos/data/images/envroll.jpg"
};
gl.glGenTextures(3, textures, 0); // Create The Texture
for (int loop = 0; loop < 3; loop++) // Loop Through 5 Textures
{
String textureName = textureNames[loop];
TextureReader.Texture texture = TextureReader.readTexture(textureName);
gl.glBindTexture(GL.GL_TEXTURE_2D, textures[loop]);
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB8, texture.getWidth(), texture.getHeight(), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, texture.getPixels());
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);
}
}
public void init(GLAutoDrawable glDrawable) {
GL gl = glDrawable.getGL();
try {
loadGLTextures(gl); // If Loading The Textures Failed
} catch (IOException e) {
throw new RuntimeException(e);
}
gl.glShadeModel(GL.GL_SMOOTH); // Enable Smooth Shading
gl.glClearColor(0.2f, 0.5f, 1.0f, 1.0f); // Background
gl.glClearDepth(1.0f); // Depth Buffer Setup
gl.glClearStencil(0); // Clear The Stencil Buffer To 0
gl.glEnable(GL.GL_DEPTH_TEST); // Enables Depth Testing
gl.glDepthFunc(GL.GL_LEQUAL); // The Type Of Depth Testing To Do
gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST); // Really Nice Perspective Calculations
gl.glEnable(GL.GL_TEXTURE_2D); // Enable 2D Texture Mapping
gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, lightAmbient, 0); // Set The Ambient Lighting For Light0
gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, lightDiffuse, 0); // Set The Diffuse Lighting For Light0
gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lightPosition, 0); // Set The Position For Light0
gl.glEnable(GL.GL_LIGHT0); // Enable Light 0
gl.glEnable(GL.GL_LIGHTING); // Enable Lighting
q = glu.gluNewQuadric(); // Create A New Quadratic
glu.gluQuadricNormals(q, GL.GL_SMOOTH); // Generate Smooth Normals For The Quad
glu.gluQuadricTexture(q, true); // Enable Texture Coords For The Quad
gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP); // Set Up Sphere Mapping
gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP); // Set Up Sphere Mapping
}
private void DrawObject(GL gl, GLU glu) // Draw Our Ball
{
gl.glColor3f(1.0f, 1.0f, 1.0f); // Set Color To White
gl.glBindTexture(GL.GL_TEXTURE_2D, textures[1]); // Select Texture 2 (1)
glu.gluSphere(q, 0.35f, 32, 16); // Draw First Sphere
gl.glBindTexture(GL.GL_TEXTURE_2D, textures[2]); // Select Texture 3 (2)
gl.glColor4f(1.0f, 1.0f, 1.0f, 0.4f); // Set Color To White With 40% Alpha
gl.glEnable(GL.GL_BLEND); // Enable Blending
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE); // Set Blending Mode To Mix Based On SRC Alpha
gl.glEnable(GL.GL_TEXTURE_GEN_S); // Enable Sphere Mapping
gl.glEnable(GL.GL_TEXTURE_GEN_T); // Enable Sphere Mapping
glu.gluSphere(q, 0.35f, 32, 16); // Draw Another Sphere Using New Texture
// Textures Will Mix Creating A MultiTexture Effect (Reflection)
gl.glDisable(GL.GL_TEXTURE_GEN_S); // Disable Sphere Mapping
gl.glDisable(GL.GL_TEXTURE_GEN_T); // Disable Sphere Mapping
gl.glDisable(GL.GL_BLEND); // Disable Blending
}
private void DrawFloor(GL gl) // Draws The Floor
{
gl.glBindTexture(GL.GL_TEXTURE_2D, textures[0]); // Select Texture 1 (0)
gl.glBegin(GL.GL_QUADS); // Begin Drawing A Quad
gl.glNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
gl.glTexCoord2f(0.0f, 1.0f); // Bottom Left Of Texture
gl.glVertex3f(-2.0f, 0.0f, 2.0f); // Bottom Left Corner Of Floor
gl.glTexCoord2f(0.0f, 0.0f); // Top Left Of Texture
gl.glVertex3f(-2.0f, 0.0f, -2.0f); // Top Left Corner Of Floor
gl.glTexCoord2f(1.0f, 0.0f); // Top Right Of Texture
gl.glVertex3f(2.0f, 0.0f, -2.0f); // Top Right Corner Of Floor
gl.glTexCoord2f(1.0f, 1.0f); // Bottom Right Of Texture
gl.glVertex3f(2.0f, 0.0f, 2.0f); // Bottom Right Corner Of Floor
gl.glEnd(); // Done Drawing The Quad
}
private void update() {
if (zoomIn)
zoom += 0.05f;
if (zoomOut)
zoom -= 0.05f;
if (increaseHeight)
height += 0.03f;
if (decreaseHeight)
height -= 0.03f;
if (increaseXspeed)
xspeed += 0.08f;
if (decreaseXspeed)
xspeed -= 0.08f;
if (increaseYspeed)
yspeed += 0.08f;
if (decreaseYspeed)
yspeed -= 0.08f;
}
public void display(GLAutoDrawable glDrawable) {
update();
GL gl = glDrawable.getGL();
// Clear Screen, Depth Buffer & Stencil Buffer
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT);
// Clip Plane Equations
double eqr[] = {0.0f, -1.0f, 0.0f, 0.0f}; // Plane Equation To Use For The Reflected Objects
gl.glLoadIdentity(); // Reset The Modelview Matrix
gl.glTranslatef(0.0f, -0.6f, zoom); // Zoom And Raise Camera Above The Floor (Up 0.6 Units)
gl.glColorMask(false, false, false, false); // Set Color Mask
gl.glEnable(GL.GL_STENCIL_TEST); // Enable Stencil Buffer For "marking" The Floor
gl.glStencilFunc(GL.GL_ALWAYS, 1, 1); // Always Passes, 1 Bit Plane, 1 As Mask
gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_REPLACE); // We Set The Stencil Buffer To 1 Where We Draw Any Polygon
// Keep If Test Fails, Keep If Test Passes But Buffer Test Fails
// Replace If Test Passes
gl.glDisable(GL.GL_DEPTH_TEST); // Disable Depth Testing
DrawFloor(gl); // Draw The Floor (Draws To The Stencil Buffer)
// We Only Want To Mark It In The Stencil Buffer
gl.glEnable(GL.GL_DEPTH_TEST); // Enable Depth Testing
gl.glColorMask(true, true, true, true); // Set Color Mask to TRUE, TRUE, TRUE, TRUE
gl.glStencilFunc(GL.GL_EQUAL, 1, 1); // We Draw Only Where The Stencil Is 1
// (I.E. Where The Floor Was Drawn)
gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); // Don't Change The Stencil Buffer
gl.glEnable(GL.GL_CLIP_PLANE0); // Enable Clip Plane For Removing Artifacts
// (When The Object Crosses The Floor)
gl.glClipPlane(GL.GL_CLIP_PLANE0, eqr, 0); // Equation For Reflected Objects
gl.glPushMatrix(); // Push The Matrix Onto The Stack
gl.glScalef(1.0f, -1.0f, 1.0f); // Mirror Y Axis
gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lightPosition, 0); // Set Up Light0
gl.glTranslatef(0.0f, height, 0.0f); // Position The Object
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); // Rotate Local Coordinate System On X Axis
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); // Rotate Local Coordinate System On Y Axis
DrawObject(gl, glu); // Draw The Sphere (Reflection)
gl.glPopMatrix(); // Pop The Matrix Off The Stack
gl.glDisable(GL.GL_CLIP_PLANE0); // Disable Clip Plane For Drawing The Floor
gl.glDisable(GL.GL_STENCIL_TEST); // We Don't Need The Stencil Buffer Any More (Disable)
gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lightPosition, 0); // Set Up Light0 Position
gl.glEnable(GL.GL_BLEND); // Enable Blending (Otherwise The Reflected Object Wont Show)
gl.glDisable(GL.GL_LIGHTING); // Since We Use Blending, We Disable Lighting
gl.glColor4f(1.0f, 1.0f, 1.0f, 0.8f); // Set Color To White With 80% Alpha
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); // Blending Based On Source Alpha And 1 Minus Dest Alpha
DrawFloor(gl); // Draw The Floor To The Screen
gl.glEnable(GL.GL_LIGHTING); // Enable Lighting
gl.glDisable(GL.GL_BLEND); // Disable Blending
gl.glTranslatef(0.0f, height, 0.0f); // Position The Ball At Proper Height
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); // Rotate On The X Axis
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); // Rotate On The Y Axis
DrawObject(gl, glu); // Draw The Ball
xrot += xspeed; // Update X Rotation Angle By xrotspeed
yrot += yspeed; // Update Y Rotation Angle By yrotspeed
}
public void reshape(GLAutoDrawable glDrawable, int x, int y, int w, int h) {
if (h == 0) h = 1;
GL gl = glDrawable.getGL();
gl.glViewport(0, 0, w, h); // Reset The Current Viewport And Perspective Transformation
gl.glMatrixMode(GL.GL_PROJECTION); // Select The Projection Matrix
gl.glLoadIdentity(); // Reset The Projection Matrix
glu.gluPerspective(45.0f, (float) w / (float) h, 0.1f, 100.0f); // Calculate The Aspect Ratio Of The Window
gl.glMatrixMode(GL.GL_MODELVIEW); // Select The Modelview Matrix
gl.glLoadIdentity(); // Reset The ModalView Matrix
}
public void displayChanged(GLAutoDrawable glDrawable, boolean b, boolean b1) {
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -