在JOGL中,反射如同在反射的表面上再繪製物體,使其產生反射的效果。可使用javax.media.opengl.GL類別的glStencilFunc()與glStencilOp()方法處理。例如:
gl.glColorMask(false, false, false, false); gl.glDepthMask(false); gl.glEnable(GL.GL_STENCIL_TEST); gl.glStencilFunc(GL.GL_ALWAYS, 1, ~0); gl.glStencilOp(GL.GL_REPLACE, GL.GL_REPLACE, GL.GL_REPLACE); drawSurface(); gl.glColorMask(true, true, true, true); gl.glDepthMask(true); gl.glStencilFunc(GL.GL_EQUAL, 1, ~0); gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); gl.glPushMatrix(); gl.glScalef(1.0f, -1.0f, 1.0f); gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, g_lightPos, 0); drawCube(); gl.glPopMatrix(); gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, g_lightPos, 0); gl.glEnable(GL.GL_BLEND); drawSurface(); gl.glDisable(GL.GL_BLEND); gl.glPushMatrix(); gl.glDisable(GL.GL_TEXTURE_2D); gl.glDisable(GL.GL_LIGHTING); gl.glDisable(GL.GL_DEPTH_TEST); gl.glEnable(GL.GL_BLEND); gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_INCR); gl.glColor4f(0.0f, 0.0f, 0.0f, 0.5f); gl.glMultMatrixf(g_shadowMatrix, 0); drawCube(); gl.glEnable(GL.GL_TEXTURE_2D); gl.glEnable(GL.GL_DEPTH_TEST); gl.glDisable(GL.GL_BLEND); gl.glEnable(GL.GL_LIGHTING); gl.glPopMatrix(); gl.glDisable(GL.GL_STENCIL_TEST); gl.glPushMatrix(); drawCube(); gl.glPopMatrix(); |
請參考以下範例。
// 實作GLEventListener介面之方法 // 初始化JOGL public void init(GLAutoDrawable drawable) { gl = drawable.getGL(); // Clear window with color gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // set the shading model gl.glShadeModel(GL.GL_SMOOTH); // set up a single white light float lightColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, lightColor, 0); gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, lightColor, 0); gl.glEnable(GL.GL_LIGHTING); gl.glEnable(GL.GL_LIGHT0); gl.glEnable(GL.GL_DEPTH_TEST); gl.glEnable(GL.GL_TEXTURE_2D); gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE); // load the textures cubeTex = loadTexture("opengl.jpg"); marbleTex = loadTexture("marble.jpg"); gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); float[] plane = { 0.0f, 1.0f, 0.0f, 0.0f }; // dot product of plane and light position float dot = plane[0] * g_lightPos[0] + plane[1] * g_lightPos[1] + plane[1] * g_lightPos[2] + plane[3] * g_lightPos[3]; // first column g_shadowMatrix[0] = dot - g_lightPos[0] * plane[0]; g_shadowMatrix[4] = 0.0f - g_lightPos[0] * plane[1]; g_shadowMatrix[8] = 0.0f - g_lightPos[0] * plane[2]; g_shadowMatrix[12] = 0.0f - g_lightPos[0] * plane[3]; // second column g_shadowMatrix[1] = 0.0f - g_lightPos[1] * plane[0]; g_shadowMatrix[5] = dot - g_lightPos[1] * plane[1]; g_shadowMatrix[9] = 0.0f - g_lightPos[1] * plane[2]; g_shadowMatrix[13] = 0.0f - g_lightPos[1] * plane[3]; // third column g_shadowMatrix[2] = 0.0f - g_lightPos[2] * plane[0]; g_shadowMatrix[6] = 0.0f - g_lightPos[2] * plane[1]; g_shadowMatrix[10] = dot - g_lightPos[2] * plane[2]; g_shadowMatrix[14] = 0.0f - g_lightPos[2] * plane[3]; // fourth column g_shadowMatrix[3] = 0.0f - g_lightPos[3] * plane[0]; g_shadowMatrix[7] = 0.0f - g_lightPos[3] * plane[1]; g_shadowMatrix[11] = 0.0f - g_lightPos[3] * plane[2]; g_shadowMatrix[15] = dot - g_lightPos[3] * plane[3]; } // 載入圖像以作為貼圖之用 private Texture loadTexture(String filename) { com.sun.opengl.util.texture.Texture tex = null; // Get current classloader ClassLoader cl = this.getClass().getClassLoader(); try { // 載入圖像檔案 tex = com.sun.opengl.util.texture.TextureIO.newTexture( cl.getResourceAsStream("images/" + filename), false, TextureIO.JPG); // 設定Texture的參數 tex.setTexParameteri(GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); tex.setTexParameteri(GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT); tex.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); tex.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); } catch(Exception e) { System.out.println("Error loading texture " + filename); } return tex; } // 繪製圖形 public void display(GLAutoDrawable drawable) { gl = drawable.getGL(); gl.glLoadIdentity(); glu.gluLookAt(0.0, 3.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // Clear gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT); // rotate the scene angle += 3.0; gl.glRotated(-angle/8.0, 0.0, 1.0, 0.0); gl.glRotated(10.0 * Math.sin(angle/45.0), 1.0, 0.0, 0.0); gl.glColorMask(false, false, false, false); gl.glDepthMask(false); gl.glEnable(GL.GL_STENCIL_TEST); gl.glStencilFunc(GL.GL_ALWAYS, 1, ~0); gl.glStencilOp(GL.GL_REPLACE, GL.GL_REPLACE, GL.GL_REPLACE); drawSurface(); gl.glColorMask(true, true, true, true); gl.glDepthMask(true); gl.glStencilFunc(GL.GL_EQUAL, 1, ~0); gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); gl.glPushMatrix(); gl.glScalef(1.0f, -1.0f, 1.0f); gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, g_lightPos, 0); drawCube(); gl.glPopMatrix(); gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, g_lightPos, 0); gl.glEnable(GL.GL_BLEND); drawSurface(); gl.glDisable(GL.GL_BLEND); gl.glPushMatrix(); gl.glDisable(GL.GL_TEXTURE_2D); gl.glDisable(GL.GL_LIGHTING); gl.glDisable(GL.GL_DEPTH_TEST); gl.glEnable(GL.GL_BLEND); gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_INCR); gl.glColor4f(0.0f, 0.0f, 0.0f, 0.5f); gl.glMultMatrixf(g_shadowMatrix, 0); drawCube(); gl.glEnable(GL.GL_TEXTURE_2D); gl.glEnable(GL.GL_DEPTH_TEST); gl.glDisable(GL.GL_BLEND); gl.glEnable(GL.GL_LIGHTING); gl.glPopMatrix(); gl.glDisable(GL.GL_STENCIL_TEST); gl.glPushMatrix(); drawCube(); gl.glPopMatrix(); } private void drawSurface(){ float[] surfaceColor = { 1.0f, 1.0f, 1.0f, 0.6f }; gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, surfaceColor, 0); gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, surfaceColor, 0); gl.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, 200.0f); // 啟用貼圖 cubeTex.enable(); marbleTex.enable(); // 繫結貼圖 marbleTex.bind(); gl.glBegin(GL.GL_QUADS); gl.glNormal3f(0.0f, 1.0f, 0.0f); float x = -5.0f; float z = -5.0f; for (int i = 0; i < 10; i++, x += 1.0f) { for (int j = 0; j < 10; j++, z += 1.0f) { gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(x, 0.0f, z); gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(x + 1.0f, 0.0f, z); gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(x + 1.0f, 0.0f, z + 1.0f); gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(x, 0.0f, z + 1.0f); } z = -5.0f; } gl.glEnd(); marbleTex.disable(); } |
【執行結果】
【參考資料】
[1] Java Platform, Standard Edition 7, API Specification.
[2] JOGL.
[3] 黃嘉輝,完全探索Java遊戲程式設計,上奇資訊。
© Chia-Hui Huang
沒有留言:
張貼留言