jogl 纹理贴图

用到了nehe的common中的TextureReader类


package test.d717;

 * Copyright (c) 2015, 2015  Technologies Corporation.

import java.awt.FlowLayout;
import java.awt.Frame;
import java.io.IOException;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;
import javax.swing.SwingUtilities;

import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

import com.sun.opengl.util.FPSAnimator;

public class BasicF implements GLEventListener {

	static Display display;

	static Shell shell;

	static FPSAnimator animator;

	/**
	 * 纹理理标号
	 */
	private int texture_int;

	private GL gl;

	private final GLU glu = new GLU();

	/**
	 * 申请纹理
	 */
	private int genTexture(final GL gl) {
		final int[] tmp = new int[1];
		gl.glGenTextures(1, tmp, 0);
		return tmp[0];
	}

	/**
	 * 生成纹理
	 */
	private void makeRGBTexture(final GL gl, final GLU glu, final TextureReader.Texture img, final int target, final boolean mipmapped) {
		if (mipmapped) {
			/**
			 * 生成纹理,gluBuild2DMipmaps() 和 glTexImage2D() 两个都是生成纹理的。
			 * 两者的区别就是:
			 * 使用glTexImage2D()时所采用的位图文件分辨率必须为:64×64、128×128、256×256三种格式,如果其他大小则会出现绘制不正常。
			 * gluBuild2DMipmaps()支持任意分辨率位图文件。
			 */
			glu.gluBuild2DMipmaps(target, GL.GL_RGB8, img.getWidth(), img.getHeight(), GL.GL_RGB, GL.GL_UNSIGNED_BYTE, img.getPixels());
		} else {

			/**
			 * 下面一行告诉OpenGL此纹理是一个2D纹理 ( GL_TEXTURE_2D )。
			 * 参数“0”代表图像的详细程度,通常就由它为零去了。
			 * 参数三是数据的成分数。因为图像是由红色数据,绿色数据,蓝色数据三种组分组成。
			 * img.getWidth() 是纹理的宽度。如果您知道宽度,您可以在这里填入,
			 * 但计算机可以很容易的为您指出此值。
			 * img.getHeight() 是纹理的高度。参数零是边框的值,一般就是“0”。
			 * GL_RGB 告诉OpenGL图像数据由红、绿、蓝三色数据组成。
			 * GL_UNSIGNED_BYTE 意味着组成图像的数据是无符号字节类型的。
			 * img.getPixels()告诉OpenGL纹理数据的来源。此例中指向存放在 TextureImage[0] 记录中的数据。
			 */
			gl.glTexImage2D(target, 0, 3, img.getWidth(), img.getHeight(), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, img.getPixels());

		}
	}

	@Override
	public void init(final GLAutoDrawable drawable) { // 初始函数

		gl = drawable.getGL();
		gl.glClearColor(0.0f, 0.0f, 0.0f, 1f); // 设置背景颜色
		// gl.glViewport(0, 0, 100, 100); // 视点大小,一个视口时候没必要用这个
		gl.glMatrixMode(GL.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluOrtho2D(0, 100, 0.0, 100.0); // 使坐标系统出现在GL里,此时屏幕中最左面是坐标0,右面是100,最下0,嘴上100

		gl.glEnable(GL.GL_TEXTURE_2D);// 开启纹理
		texture_int = genTexture(gl);
		gl.glBindTexture(GL.GL_TEXTURE_2D, texture_int);// 绑定纹理
		TextureReader.Texture texture_A = null;
		try {
			// 得到图片所对应的纹理
			texture_A = TextureReader.readTexture("demos/data/images/cc.bmp");// xiaogang.png cc.bmp
		} catch (final IOException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		makeRGBTexture(gl, glu, texture_A, GL.GL_TEXTURE_2D, false);
		/**
		 * 下面的两行告诉OpenGL在显示图像时,当它比放大得原始的纹理大
		 * ( GL_TEXTURE_MAG_FILTER )或缩小得比原始得纹理小
		 * ( GL_TEXTURE_MIN_FILTER )时OpenGL采用的滤波方式。
		 * 通常这两种情况下我都采用 GL_LINEAR 。这使得纹理从很远处到离屏幕很
		 * 近时都平滑显示。使用 GL_LINEAR 需要CPU和显卡做更多的运算。
		 * 如果您的机器很慢,您也许应该采用 GL_NEAREST 。过滤的纹理在放大的时候,
		 * 看起来斑驳的很『译者注:马赛克啦』。您也可以结合这两种滤波方式。
		 * 在近处时使用 GL_LINEAR ,远处时 GL_NEAREST 。
		 */
		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);
		// TODO
		System.out.println(texture_A.getWidth() + "," + texture_A.getHeight());
	}

	@Override
	public void display(final GLAutoDrawable drawable) { // 画图函数

		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); // 填充背景颜色

		gl.glColor3f(255.0f, 255.0f, 255.0f); // 设置GL的画图颜色,也就是画刷的颜色

		/**
		 * 如果您在您的场景中使用多个纹理,您应该使用来
		 * glBindTexture(GL_TEXTURE_2D, texture_int[ 所使用纹理对应的数字 ])
		 * 选择要绑定的纹理。当您想改变纹理时,应该绑定新的纹理。
		 * 有一点值得指出的是,您不能在 glBegin() 和 glEnd() 之间绑定纹理,
		 * 必须在 glBegin() 之前或 glEnd() 之后绑定。
		 */
		gl.glBindTexture(GL.GL_TEXTURE_2D, texture_int);

		gl.glBegin(GL.GL_QUADS);
		gl.glTexCoord2f(0.0f, 0.0f);// 左下
		gl.glVertex2f(0f, 0f);
		gl.glTexCoord2f(1.0f, 0.0f);// 右下
		gl.glVertex2f(100f, 0f);
		gl.glTexCoord2f(1.0f, 1.0f);// 右上
		gl.glVertex2f(100f, 100f);
		gl.glTexCoord2f(0.0f, 1.0f);// 左上
		gl.glVertex2f(0f, 100f);
		gl.glEnd();

		gl.glColor3f(10.0f, 0.0f, 0.0f); // 设置GL的画图颜色,也就是画刷的颜色

		gl.glBegin(GL.GL_LINES);
		gl.glVertex2d(5, 5);
		gl.glVertex2d(95, 5);
		gl.glEnd();

		gl.glFlush();

	}

	@Override
	public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {

	}

	@Override
	public void displayChanged(final GLAutoDrawable drawable, final boolean modeChanged, final boolean deviceChanged) {

	}

	public Frame creatSWT() {
		display = Display.getDefault();
		shell = new Shell();
		shell.setSize(550, 550);
		shell.setText("SWT_OpenGL");
		shell.setLayout(null);
		final Composite compSWT = new Composite(shell, SWT.EMBEDDED);// SWT.EMBEDDED必须
		compSWT.setSize(500, 500);
		compSWT.setLocation(0, 0);
		final java.awt.Frame frame = SWT_AWT.new_Frame(compSWT);
		frame.setLayout(new FlowLayout());
		shell.layout();
		shell.open();
		return frame;
	}

	public static void main(final String[] args) {

		final GLCapabilities capabilities = new GLCapabilities();
		final GLCanvas glcanvas = new GLCanvas(capabilities);// 创建画布
		final BasicF basicFrame = new BasicF();
		glcanvas.addGLEventListener(basicFrame);// basicFrame重写了GLEventListener的画图的方法
		glcanvas.setSize(500, 500);
		animator = new FPSAnimator(glcanvas, 60, true);

		final Frame frame = basicFrame.creatSWT();
		frame.add(glcanvas);// 把画布放进 窗口内

		SwingUtilities.invokeLater(

		new Runnable() {

			@Override
			public void run() {

				animator.start(); // 开始动画线程

			}

		}

		);

		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		animator.stop();
		display.dispose();
	}

}



over

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值