OpenGL 学习笔记-2015.4.18——立方体纹理映射-天空盒子-环境映射

立方体映射(cube-map)纹理是一种特殊类型的纹理,用于环境映射,使用一组图像并把他们作为立方体的面。立方体映射的6个面用正方形并且大小相同的6个子纹理表示。要从立方体纹理中采样的时候,使用的纹理坐标是3维,并且被看做来自原点的方向!方向指向用来读取纹理的立方体映射表面的位置。在这里例子中,有关于环境映射的代码,主要思想是通过观察向量和表面的法向量反射来确定采样的纹理坐标。

通过将一个新的纹理名绑定到GL_TEXTURE_CUBE_MAP纹理目标,然后调用glTexStorage2D()以GL_TEXTUR_CUBE_MAP作为参数为立方体纹理映射分配储存空间,这个调用将为立方体纹理映射的所有6个面分配内存。分配内存后,立方体纹理映射用6个特殊的目标集合表示,分别是:GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z.或者调用glTexImage2D()以6个特殊标识符分别分配6个面的内存,设置数据。

for (int face = 0; face < 6; face++)

{

glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face,

level,

image->internalFormat,

image->mip[level].width, image->mip[level].height,

0,

image->format, image->type,

ptr + image->sliceStride * face);

}

GL_TEXTURE_CUBE_MAP_POSITIVE_X... 是6个连续的整数。

glEnable( GL_TEXTURE_CUBE_MAP_SEAMLESS ):开启GL_TEXTURE_CUBE_MAP_SEAMLESS在天空盒子的边缘将对两个交界面进行采样混合,否则边缘将采用单边像素,会出现明显的裂缝。

实例代码:例子代码中实现了天空盒子和环境映射。在关键地方有简单的注释。

#include "cubeTexture\cubeTexture.h"
#include "vbm.h"
#include "vutils.h"
#include "vmath.h"
#include "vermilion.h"

namespace cubeTexture
{
	float aspect = 800.0/600.0f;
	GLuint skybox_prog;
	GLuint object_prog;
	GLuint vao;

	GLuint cube_vbo;
	GLuint cube_element_buffer;

	GLuint tex;
	GLint skybox_rotate_loc;

	GLint object_mat_mvp_loc;
	GLint object_mat_mv_loc;
	VBObject object;

	void cubeTextureInit()
	{
		skybox_prog = glCreateProgram();
		static const char skybox_shader_vs[] =
			"#version 330 core\n"
			"\n"
			"layout (location = 0) in vec3 in_position;\n"
			"\n"
			"out vec3 tex_coord;\n"
			"\n"
			"uniform mat4 tc_rotate;\n"
			"\n"
			"void main(void)\n"
			"{\n"
			"    gl_Position = tc_rotate * vec4(in_position, 1.0);\n"
			"    tex_coord = in_position;\n"
			"}\n";

		static const char skybox_shader_fs[] =
			"#version 330 core\n"
			"\n"
			"in vec3 tex_coord;\n"
			"\n"
			"layout (location = 0) out vec4 color;\n"
			"\n"
			"uniform samplerCube tex;\n"
			"\n"
			"void main(void)\n"
			"{\n"
			"    color = texture(tex, tex_coord);\n"
			"}\n";

		vglAttachShaderSource(skybox_prog, GL_VERTEX_SHADER, skybox_shader_vs);
		vglAttachShaderSource(skybox_prog, GL_FRAGMENT_SHADER, skybox_shader_fs );

		glLinkProgram( skybox_prog );

		static const char object_shader_vs[] =
			"#version 330 core\n"
			"\n"
			"layout (location = 0) in vec4 in_position;\n"
			"layout (location = 1) in vec3 in_normal;\n"
			"\n"
			"out vec3 vs_fs_normal;\n"
			"out vec3 vs_fs_position;\n"
			"\n"
			"uniform mat4 mat_mvp;\n"
			"uniform mat4 mat_mv;\n"
			"\n"
			"void main(void)\n"
			"{\n"
			"    gl_Position = mat_mvp * in_position;\n"
			"    vs_fs_normal = mat3(mat_mv) * in_normal;\n"
			"    vs_fs_position = (mat_mv * in_position).xyz;\n"
			"}\n";

		static const char object_shader_fs[] =
			"#version 330 core\n"
			"\n"
			"in vec3 vs_fs_normal;\n"
			"in vec3 vs_fs_position;\n"
			"\n"
			"layout (location = 0) out vec4 color;\n"
			"\n"
			"uniform samplerCube tex;\n"
			"\n"
			"void main(void)\n"
			"{\n"
			"    vec3 tc =  reflect(vs_fs_position, normalize(vs_fs_normal));\n"//这里的原理其实是根据摄像机与观察点形成的向量(默认摄像机在(0,0,0,)),
																				//和观察点顶点法线计算最终顶点纹理坐标。有点类似于关照反射的计算。
																				//并且这里的所有的计算也是在观察空间内计算的,因为我们之前就进行了,model view变换。
			"    color = vec4(0.3, 0.2, 0.1, 1.0) + vec4(0.97, 0.83, 0.79, 0.0) * texture(tex, tc);\n"
			"}\n";

		object_prog = glCreateProgram();

		vglAttachShaderSource( object_prog, GL_VERTEX_SHADER, object_shader_vs );
		vglAttachShaderSource( object_prog, GL_FRAGMENT_SHADER, object_shader_fs );

		glLinkProgram( object_prog );

		glGenBuffers( 1, &cube_vbo );
		glBindBuffer( GL_ARRAY_BUFFER, cube_vbo );

		static const GLfloat cube_vertices[] =
		{
			-1.0f, -1.0f, -1.0f,
			-1.0f, -1.0f, 1.0f,
			-1.0f, 1.0f, -1.0f,
			-1.0f, 1.0f, 1.0f,
			1.0f, -1.0f, -1.0f,
			1.0f, -1.0f, 1.0f,
			1.0f, 1.0f, -1.0f,
			1.0f, 1.0f, 1.0f
		};

		static const GLushort cube_indices[] =
		{
			0, 1, 2, 3, 6, 7, 4, 5,         // First strip
			2, 6, 0, 4, 1, 5, 3, 7          // Second strip
		};

		glBufferData( GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW );

		glGenVertexArrays( 1, &vao );
		glBindVertexArray( vao );

		glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
		glEnableVertexAttribArray(0);

		glGenBuffers( 1, &cube_element_buffer );
		glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, cube_element_buffer );
		glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_indices), cube_indices, GL_STATIC_DRAW );

		skybox_rotate_loc = glGetUniformLocation(skybox_prog, "tc_rotate");
		object_mat_mvp_loc = glGetUniformLocation(object_prog, "mat_mvp");
		object_mat_mv_loc = glGetUniformLocation(object_prog, "mat_mv");

		vglImageData image;

		tex = vglLoadTexture("../8edlib/media/TantolundenCube.dds", 0, &image);

		vglUnloadImage(&image);

		object.LoadFromVBM("../8edlib/media/unit_torus.vbm", 0, 1, 2 );
	}

	void cubeTextureUpdate( float delta )
	{

	}

	void cubeTextureDisplay()
	{
		static const unsigned int start_time = GetTickCount();
		float t = float((GetTickCount() - start_time)) / float(0x3FFF);
		static float time = 1.0;
		time += 0.01;
		static const vmath::vec3 X(1.0f, 0.0f, 0.0f);
		static const vmath::vec3 Y(0.0f, 1.0f, 0.0f);
		static const vmath::vec3 Z(0.0f, 0.0f, 1.0f);

		vmath::mat4 tc_matrix( vmath::mat4::identity() );

		glClearColor( 0.0f, 0.25f, 0.3f, 1.0f );
		glClearDepth( 1.0f );
		glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

		glEnable( GL_DEPTH_TEST );
		glDepthFunc( GL_LEQUAL );
		glDisable( GL_CULL_FACE );
		glUseProgram( skybox_prog );

		glEnable( GL_TEXTURE_CUBE_MAP_SEAMLESS );//开启时,两个面的交界处会进行双边线性采样来确定边缘像素,关闭时,将只采用单边值进行设置。

		tc_matrix = vmath::perspective( 35.0f, 1.0f / aspect, 0.1f, 100.0f ) * tc_matrix;

		glUniformMatrix4fv( skybox_rotate_loc, 1, GL_FALSE, tc_matrix );
		glBindVertexArray(vao);
		glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, cube_element_buffer );

		glDrawElements( GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_SHORT, NULL );
		glDrawElements( GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_SHORT, BUFFER_OFFSET( 8 * sizeof(GLushort) ) );

		glUseProgram( object_prog );

		tc_matrix = vmath::translate( vmath::vec3(0.0f, 0.0f, -4.0f) ) *
			vmath::rotate(80.0f * 3.0f * time, Y) * vmath::rotate(70.0f * 3.0f * time, Z);

		glUniformMatrix4fv( object_mat_mv_loc, 1, GL_FALSE, tc_matrix );

		tc_matrix = vmath::perspective(35.0f, 1.0f / aspect, 0.1f, 100.0f) * tc_matrix;
		glUniformMatrix4fv( object_mat_mvp_loc, 1, GL_FALSE, tc_matrix );

		glClear( GL_DEPTH_BUFFER_BIT );

		object.Render();

		GLenum e;

		e = glGetError();
	}
};

运行效果:

时间: 2024-12-27 23:52:52

OpenGL 学习笔记-2015.4.18——立方体纹理映射-天空盒子-环境映射的相关文章

【Unity 3D】学习笔记三十三:游戏元素——天空盒子

天空盒子 一般的3D游戏都会有着北京百年一遇的蓝天,让人惊叹不已.其实天空这个效果没有什么神秘的只需用到天空盒子这个组件就行,可以将天空设想成一个巨大的盒子,这个盒子将整个游戏视图和所有的游戏元素包含其中.在unity中制作天空盒子非常方便,只需要像设置其他组件一样设置下就行了.在制作天空盒子之前,我们需要搜集一些天空的贴图,不过,unity很方便的为开发者提供了天空盒子的资源包.首先在project视图中点击鼠标右键,然后选择import package--skyboxes即可添加天空盒子的资

OpenGL学习笔记-2015.3.24——transform feedback缓存&amp;粒子系统示例分析

transform feedback是OpenGL中比较酷炫的特性之一,他让客户端应用程序可以获取到渲染流水线上的顶点数据.基于这一特性实现了基于z-pass场景决策渲染技术,当然在此并没有去了解何为z-pass场景决策渲染技术,总之是一个可以有效减少渲染数据的输送.这里只是通过一个简单的例子系统,去了解transform feedback对象的使用方法. 正文: 1.transform feedback: transform feedback是OpenGL渲染管线中,顶点处理阶段结束之后,图元

selenium2 webdriver学习笔记2015.10.18

以下程序实现126邮箱的写信.存草稿及预览验证 package email;import static org.junit.Assert.fail; import java.util.concurrent.TimeUnit; import org.junit.After;import org.junit.Before;import org.junit.Test;import org.openqa.selenium.*;import org.openqa.selenium.WebDriver.*;

OpenGL学习笔记2 —— 画立方体

#include <windows.h> // windows系统要加这个.因为下面2个头文件的一些宏是在这个文件中定义的 #include <gl/Gl.h> #include <gl/glut.h> //这两个头文件在OpenGL程序中几乎必加. //<<<<<<<<<<<<<<<<<<<<<<< myInit >>&

【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

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> //标准输入输出,用来打印

【OpenGL 学习笔记04】顶点数组

通过之前的学习,我们知道,如果要绘制一个几何图形,那就要不断的调用绘制函数,比如绘制一个20条边的多边形,起码要调用22条函数(包含glBegin和glEnd). 所以OpenGL提供了一系列的顶点数组函数减少函数调用的次数来提高性能.而且使用顶点还可以避免顶点共享的冗余处理. 1.简单示例 先来回顾一下之前我们是怎么画直线的: void drawOneLine(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2) { glBegin(GL_LINES); g