OpenGL学习(七)纹理映射

纹理映射

    一m*n的像素数组,我们并不将其看做有离散元素构成的数组,而是将其视作一个连续数组。该数组中的任意一点通过变量s和t来定义。则每个坐标(s,t)都对应一个像素值。现在考虑一个三维空间中的一个几何对象。其表面上的每一点都对应于三维世界坐标系中的一个坐标(x,y,z),如果能通过一对函数映射将对象坐标系的每一点(x,y,z)与纹理坐标中的一点(s,t)建立关联,则可用纹理图像中的颜色或灰度值来确定对象表面上可见点的颜色。

OpenGL对此问题的解决方法是强制应用程序为每个顶点都定义纹理坐标。然后插值。

纹理图的创建

    void glTexImage2D(GLenum target,GLint level,GLint iformat,

GLsizei width,GLsizei height,GLint border,

GLenum format,GLenum type,GLvoid* texels)

//该函数依据类型为type,格式为format的数组texels创建一个二维的大小为height*width的纹理。该纹理的边界被指定为b个纹理元宽。图像的数据格式为iformat。level用于多级渐进纹理。

使用纹理前先开启该功能:

glEnable(GL_TEXTURE_2D);

注:纹理图像的维数必须为2的整数次幂。

同理创建一维纹理和三维纹理也是用一样的方式glTexImage1D()和glTexImage3D().

纹理坐标

    纹理坐标也是OpenGL状态的一部分。与顶点一样,其内部形式也是四维的:

void glTexCoord<1234>(sifd)(type scoord,.....)

void glTexCoord<1234>(sifd)v(type* v)

二维情况下,我们假定glTexCoord()指定的纹理元素组在一个连续矩形中,该矩形中的任意一点的为奴隶坐标都位于区间(0,1)内。所以左下角坐标为(0,0),右上角坐标为(1,1)

纹理参数

    void glTexParameter<if>(GLenum target,GLenum name,type value)

void glTexParamer<if>v(GLenum target,GLenum name,type value)

//target为GL_TEXTURE_1D、GL_TEXTURE_2D或GL_TEXTURE_3D,将参数name设为true

这些必要的参数决定了当s,t,r或q的值超过(0,1)时做何处理以及如何运用采样和滤波

对于超出(0,1)的有两种处理方式:

GL_REPEATE:若该值为正,则直接使用其小数部分,若为负,则取其与其相加为正的最小整数。

GL_CLAMP:若为负,强制取0,若超过1,强制取1。

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEATE)

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEATE)

glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);

glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);

绘制一个旋转的纹理立方体:

#include <GL/glut.h>

	GLfloat vertices[][3] = {{-1.0,-1.0,-1.0},{1.0,-1.0,-1.0},
	{1.0,1.0,-1.0}, {-1.0,1.0,-1.0}, {-1.0,-1.0,1.0}, 
	{1.0,-1.0,1.0}, {1.0,1.0,1.0}, {-1.0,1.0,1.0}};

	GLfloat colors[][4] = {{0.0,0.0,0.0,0.5},{1.0,0.0,0.0,0.5},
	{1.0,1.0,0.0,0.5}, {0.0,1.0,0.0,0.5}, {0.0,0.0,1.0,0.5}, 
	{1.0,0.0,1.0,0.5}, {1.0,1.0,1.0,0.5}, {0.0,1.0,1.0,0.5}};

void polygon(int a, int b, int c , int d)
{

/* draw a polygon via list of vertices */

 	glBegin(GL_POLYGON);
		glColor4fv(colors[a]);
		glTexCoord2f(0.0,0.0); 
		glVertex3fv(vertices[a]);
		glColor4fv(colors[b]); 
		glTexCoord2f(0.0,1.0); 
		glVertex3fv(vertices[b]);
		glColor4fv(colors[c]); 
		glTexCoord2f(1.0,1.0); 
		glVertex3fv(vertices[c]);
		glColor4fv(colors[d]); 
		glTexCoord2f(1.0,0.0); 
		glVertex3fv(vertices[d]);
	glEnd();
																										}

void colorcube(void)
{

/* map vertices to faces */

	polygon(0,3,2,1);
	polygon(2,3,7,6);
	polygon(3,0,4,7);
	polygon(1,2,6,5);
	polygon(4,5,6,7);
	polygon(5,4,0,1);
}

static GLfloat theta[] = {0.0,0.0,0.0};
static GLint axis = 2;

void display(void)
{
/* display callback, clear frame buffer and z buffer,
   rotate cube and draw, swap buffers */

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glRotatef(theta[0], 1.0, 0.0, 0.0);
	glRotatef(theta[1], 0.0, 1.0, 0.0);
	glRotatef(theta[2], 0.0, 0.0, 1.0);

 	colorcube();

	glutSwapBuffers();
}

void spinCube()
{

/* Idle callback, spin cube 2 degrees about selected axis */

	theta[axis] += 0.1;
	if( theta[axis] > 360.0 ) theta[axis] -= 360.0;
	/* display(); */
	glutPostRedisplay();
}

void mouse(int btn, int state, int x, int y)
{

/* mouse callback, selects an axis about which to rotate */

	if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) axis = 0;
	if(btn==GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) axis = 1;
	if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) axis = 2;
}

void myReshape(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (w <= h)
        glOrtho(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w,
            2.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);
    else
        glOrtho(-2.0 * (GLfloat) w / (GLfloat) h,
            2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0, -10.0, 10.0);
    glMatrixMode(GL_MODELVIEW);
}

void key(unsigned char k, int x, int y)
{
	if(k == ‘1‘) glutIdleFunc(spinCube);
	if(k == ‘2‘) glutIdleFunc(NULL);
}

void
main(int argc, char **argv)
{
   GLubyte image[64][64][3];
   int i, j, c;
   for(i=0;i<64;i++)
   {
     for(j=0;j<64;j++)
     {
       c = ((((i&0x8)==0)^((j&0x8))==0))*255;
       image[i][j][0]= (GLubyte) c;
       image[i][j][1]= (GLubyte) c;
       image[i][j][2]= (GLubyte) c;
     }
   }
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutCreateWindow("colorcube");

/* need both double buffering and z buffer */

	glutReshapeFunc(myReshape);
	glutDisplayFunc(display);
	glutIdleFunc(spinCube);
 	glutMouseFunc(mouse);
	glutKeyboardFunc(key);
	glClearColor(1.0,1.0,1.0,1.0);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);

   glTexImage2D(GL_TEXTURE_2D,0,3,64,64,0,GL_RGB,GL_UNSIGNED_BYTE, image);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); 

    glutMainLoop();
}

运行得到:

时间: 2024-10-13 18:24:13

OpenGL学习(七)纹理映射的相关文章

OpenGL学习进程(10)第七课:四边形绘制与动画基础

    本节是OpenGL学习的第七个课时,下面以四边形为例介绍绘制OpenGL动画的相关知识:     (1)绘制几种不同的四边形: 1)四边形(GL_QUADS) OpenGL的GL_QUADS图元用于绘制四边形,它根据每四个顶点绘制一个四边形. 注意:在使用四边形时必需记住四边形的四个角必须位于同一个平面中(不存在弯曲的四边形). 2)四边形带(GL_QUAD_STRIP) 该图元指定一个连接的四边形带.它们都保持相同方向的环绕. 3)通用多边形GL_POLYGON 我们可以用它绘制任意数

OpenGL学习进程(3)第一课:初始化窗体

    本节是OpenGL学习的第一个课时,下面介绍如何初始化一个窗体:     (1)显示一个有蓝色背景的窗体: #include <GL/glut.h> #include <stdlib.h> void display(void) { /* clear all pixels */ glClear (GL_COLOR_BUFFER_BIT); glFlush (); } int main(int argc, char** argv) { glutInit(&argc, a

拓幻图形学工程师教学手册(第一讲)|一字一字敲出OpenGL学习教程

动机首先申明,我是拓幻科技图形处理工程师,自己接触OpenGL,图形图像等方面也有六年多了,很多人其实并不了解这方面,也不了解如何系统地去学,我觉得基于我硕士时期的课程和经验给大家.这些资料和经验也得感谢我的老师,来自普渡大学的终生教授迈克 贝利(Mike Bailey). 以此连载OpenGL学习教程,给大家讲解,一起学习一下,不对之处,欢迎大家指出讨论. 所有渲染工作都离不开OpenGL, 着色器(Shader)这些,如果你和我一样对图形处理比较感兴趣的话,可能你和当初的我有着同样的困惑:如

OpenGl学习进程(7)第五课:点、边和图形(二)边

本节是OpenGL学习的第五个课时,下面介绍OpenGL边的相关知识: (1)边的概念: 数学上的直线没有宽度,但OpenGL的直线则是有宽度的.同时,OpenGL的直线必须是有限长度,而不是像数学概念那样是无限的.可以认为,OpenGL的“直线”概念与数学上的“线段”接近,它可以由两个端点来确定.     (2)如何绘制边: 1)OpenGL支持绘制三种类型的边: GL_LINES :指定两个顶点,在它们之间绘制一条直线.如果为GL_LINES指定了奇数个顶点,那么最后一个顶点会被忽略. GL

OpenGL学习 Following the Pipeline

Passing Data to the Vertex Shader Vertex Attributes At the start of the OpenGL pipeline,we use the in keyword to bring inputs into the vertex shader. Between stages,in and out can be used to form conduits from shader to shader and pass databetween th

【OpenGL 学习笔记02】宽点画线

我们要知道,有三种绘图操作是最基本的:清除窗口,绘制几何图形,绘制光栅化对象. 光栅化对象后面再解释. 1.清除窗口 比如我们可以同时清除颜色缓冲区和深度缓冲区 glClearColor (0.0, 0.0, 0.0, 0.0);//指定颜色缓冲区清除为黑色 glClearDepth(1.0);//指定深度缓冲区的清除值为1.0 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//指定要清除的缓冲区并清除 2.绘制几何图形 先要设置绘制颜色,

【opengl 学习笔记01】HelloWorld示例

<<OpenGL Programming Guide>>这本书是看了忘,忘了又看,赶脚还是把笔记做一做心里比较踏实,哈哈. 我的主题是,好记性不如烂笔头. ================================================================ 1. 下载glut库 glut库地址为:www.opengl.org/resources/libraries/glut/glutdlls37beta.zip glut全称为:OpenGL Utilit

springMVC3学习(七)--Interceptor拦截器

Spring为我们提供了:org.springframework.web.servlet.HandlerInterceptor接口, org.springframework.web.servlet.handler.HandlerInterceptorAdapter适配器, 实现这个接口或继承此类,能够很方便的实现自己的拦截器. 有下面三个方法: Action之前运行 public boolean preHandle(HttpServletRequest request, HttpServletR

OpenGL学习笔记:拾取与选择

转自:OpenGL学习笔记:拾取与选择 在开发OpenGL程序时,一个重要的问题就是互动,假设一个场景里面有很多元素,当用鼠标点击不同元素时,期待作出不同的反应,那么在OpenGL里面,是怎么知道我当前鼠标的位置是哪一个物体呢? OpenGL有一套机制,叫做Picking, 里面涉及到几个核心概念: 1. selection mode. 选择模式 2. name stack. 名字栈 3. hit record. 命中记录 4. viewing volume. 视角范围 在OpenGL的pick

OpenGL学习笔记3 —— 绘制3D物体、鼠标交互、反向变换

/* reference http://nehe.gamedev.net/article/using_gluunproject/16013/ */ #include <windows.h> // windows系统要加这个.因为下面2个头文件的一些宏是在这个文件中定义的 #include <gl/Gl.h> #include <gl/glut.h> //这两个头文件在OpenGL程序中几乎必加. #include <cstdio> //标准输入输出,用来打印