Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import com.jogamp.opengl.util.FPSAnimator;
- import javax.media.opengl.*;
- import javax.media.opengl.awt.GLCanvas;
- import javax.media.opengl.glu.GLU;
- import java.awt.*;
- import java.awt.event.WindowAdapter;
- import java.awt.event.WindowEvent;
- import java.nio.FloatBuffer;
- import java.nio.IntBuffer;
- public class JOGL2ShadowAgony implements GLEventListener {
- private IntBuffer DepthTex;
- private int DepthTexSize = 512,
- WinXSize = 640, WinYSize = 480;
- private FloatBuffer PS, PT, PR, PQ;
- private GLU glu;
- private GLProfile glp;
- private GLCapabilities caps;
- private GLCanvas canvas;
- private Frame frame;
- private FPSAnimator animator;
- public JOGL2ShadowAgony() {
- PS = FloatBuffer.allocate(4);
- PS.put(new float[]{1, 0, 0, 0});
- PT = FloatBuffer.allocate(4);
- PT.put(new float[]{0, 1, 0, 0});
- PR = FloatBuffer.allocate(4);
- PR.put(new float[]{0, 0, 1, 0});
- PQ = FloatBuffer.allocate(4);
- PQ.put(new float[]{0, 0, 0, 1});
- DepthTex = IntBuffer.allocate(DepthTexSize);
- GLProfile.initSingleton();
- glp = GLProfile.get(GLProfile.GL2);
- caps = new GLCapabilities(glp);
- canvas = new GLCanvas(caps);
- canvas.addGLEventListener(this);
- frame = new Frame("JOGL2ShadowAgony");
- frame.add(canvas);
- frame.setSize(640, 480);
- animator = new FPSAnimator(canvas, 60);
- frame.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- new Thread(new Runnable() {
- public void run() {
- animator.stop();
- System.exit(0);
- }
- }).start();
- }
- });
- frame.setVisible(true);
- animator.start();
- }
- public static void main(String[] args) {
- new JOGL2ShadowAgony();
- }
- public void init(GLAutoDrawable drawable) {
- GL2 gl = drawable.getGL().getGL2();
- glu = new GLU();
- startInit(gl);
- }
- public void reshape(GLAutoDrawable drawable, int x, int y, int width,
- int height) {
- GL2 gl = drawable.getGL().getGL2();
- if (height == 0) {
- height = 1;
- }
- float aspect = (float) width / (float) height;
- gl.glMatrixMode(GL2.GL_PROJECTION);
- gl.glLoadIdentity();
- glu.gluPerspective(45.0f, aspect, 0.1f, 100.0f);
- gl.glMatrixMode(GL2.GL_MODELVIEW);
- gl.glLoadIdentity();
- }
- public void display(GLAutoDrawable drawable) {
- GL2 gl = drawable.getGL().getGL2();
- pass1(gl);
- pass2(gl);
- }
- public void dispose(GLAutoDrawable drawable) {
- }
- private void startInit(GL2 gl) {
- // Теперь нужно создать текстуру, в которой будет содержаться информация о глубине сцены (depth map). Для этого в OpenGL существует расширение ARB_depth_texture. В нем вводятся новые внутренние форматы текстуры GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24_ARB,
- // GL_DEPTH_COMPONENT32_ARB.
- gl.glGenTextures(1, DepthTex);
- gl.glCopyTexImage2D(GL2.GL_TEXTURE_2D, 0, GL2.GL_DEPTH_COMPONENT, 0, 0,
- DepthTexSize, DepthTexSize, 0);
- // Ставим фильтрацию и клампинг:
- gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
- gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
- gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
- gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
- gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE);
- // Если depth-текстуру мы будем использовать как обычную, пусть данные трактуются как яркость:
- gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_LUMINANCE);
- // Устанавливаем режим текстуры для сравнения по Z. Z из текстуры сравнивается
- // с текстурной координатой R (Z фрагмента в базисе источника света) - для этого нужно наличие расширения GL_ARB_shadow. Если указанное сравнение (GL_LEQUAL в нашем случае) не проходит, результат будет GL_TEXTURE_COMPARE_FAIL_VALUE, иначе 1:
- gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE);
- gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_COMPARE_FUNC, GL2.GL_LEQUAL);
- gl.glTexParameterf(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 0.5f);
- // Если расширение GL_ARB_texture_ambient не поддерживается, то, когда сравнение не проходит, результатом будет 0.
- // Затем устанавливаем генерацию текстурных координат:
- gl.glTexGeni(GL2.GL_S, GL2.GL_EYE_LINEAR, GL2.GL_REFLECTION_MAP);
- gl.glTexGeni(GL2.GL_T, GL2.GL_EYE_LINEAR, GL2.GL_REFLECTION_MAP);
- gl.glTexGeni(GL2.GL_R, GL2.GL_EYE_LINEAR, GL2.GL_REFLECTION_MAP);
- gl.glTexGeni(GL2.GL_Q, GL2.GL_EYE_LINEAR, GL2.GL_REFLECTION_MAP);
- // Устанавливаем z-bias:
- gl.glPolygonOffset(4, 4);
- // Зачем нужен z-bias? Так как точность z-буфера не бесконечна, могут возникать ошибки сравнения, из-за этого будут затеняться точки, которые быть затененными не должны. Смещением глубины полигонов в первом проходе мы как бы сдвигаем точки ближе к наблюдателю, чтобы избежать артефактов z-fighting'а.
- }
- private void pass1(GL2 gl) {
- // За первый проход мы рендерим сцену с позиции источника света, и заносим depth map в текстуру. При рендеринге запрещаем запись цвета, наложение текстур, так как они нам не нужны:
- gl.glViewport(0, 0, DepthTexSize, DepthTexSize);
- // устанавливаем матрицы
- gl.glMatrixMode(GL2.GL_PROJECTION);
- gl.glLoadIdentity();
- SetLightProjection();
- gl.glMatrixMode(GL2.GL_MODELVIEW);
- gl.glLoadIdentity();
- SetLightModelview(gl);
- // подготовка и рендеринг сцены
- gl.glDisable(GL2.GL_TEXTURE_2D);
- gl.glColorMask(false, false, false, false); // запрещаем запись цвета
- gl.glEnable(GL2.GL_POLYGON_OFFSET_FILL); // разрешаем z-bias
- DoRenderScene(gl);
- gl.glCopyTexSubImage2D(GL2.GL_TEXTURE_2D, 0, 0, 0, 0, 0, DepthTexSize, DepthTexSize);
- gl.glColorMask(true, true, true, true); // разрешаем запись цвета
- gl.glDisable(GL2.GL_POLYGON_OFFSET_FILL);
- }
- private void pass2(GL2 gl) {
- // За второй проход рендерим сцену с позиции камеры, включив автоматическую генерацию текстурных координат. В текстурной матрице содержится проекционная и модельная матрицы источника света:
- // устанавливаем матрицы
- gl.glViewport(0, 0, WinXSize, WinYSize);
- gl.glMatrixMode(GL2.GL_PROJECTION);
- gl.glLoadIdentity();
- SetCameraProjection();
- gl.glMatrixMode(GL2.GL_MODELVIEW);
- gl.glLoadIdentity();
- SetCameraModelview(gl);
- // подготовка и рендеринг сцены
- gl.glEnable(GL2.GL_TEXTURE_2D);
- // Устанавливаем плоскости для генерации текстурных координат
- gl.glTexGenfv(GL2.GL_S, GL2.GL_EYE_PLANE, PS);
- gl.glTexGenfv(GL2.GL_T, GL2.GL_EYE_PLANE, PT);
- gl.glTexGenfv(GL2.GL_R, GL2.GL_EYE_PLANE, PR);
- gl.glTexGenfv(GL2.GL_Q, GL2.GL_EYE_PLANE, PQ);
- // Устанавливаем текстурную матрицу
- gl.glMatrixMode(GL2.GL_TEXTURE);
- gl.glLoadIdentity();
- // Ставим texture bias, т.е. [-1, 1] -> [0, 1]
- gl.glTranslatef(0.5f, 0.5f, 0.5f);
- gl.glScalef(0.5f, 0.5f, 0.5f);
- // Положение и проекция источника света
- SetLightProjection();
- SetLightModelview(gl);
- gl.glMatrixMode(GL2.GL_MODELVIEW);
- // Рендерим геометрию
- DoRenderScene(gl);
- }
- private void SetLightProjection() {
- glu.gluPerspective(90, DepthTexSize / DepthTexSize, 1, 500);
- }
- private void SetLightModelview(GL2 gl) {
- gl.glTranslatef(0, 0, -10);
- }
- private void SetCameraProjection() {
- glu.gluPerspective(90, WinXSize / WinYSize, 1, 500);
- }
- private void SetCameraModelview(GL2 gl) {
- gl.glTranslatef(0, -10, -10);
- gl.glRotatef(60, 1, 0, 0);
- }
- private void DoRenderScene(GL2 gl) {
- gl.glBegin(GL2.GL_QUADS);
- gl.glVertex3f(-1.0f, -1.0f, 2.0f);
- gl.glVertex3f(1.0f, -1.0f, 0.0f);
- gl.glVertex3f(1.0f, 1.0f, 0.0f);
- gl.glVertex3f(-1.0f, 1.0f, 2.0f);
- gl.glEnd();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment