opengl 把纹理映射到立方体的六个面。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opengl 把纹理映射到立方体的六个面。相关的知识,希望对你有一定的参考价值。

我知道把纹理映射到立方体的六个面,但六个面的图片都是一样的,我想实现六个面是不同的图片?怎么办?帮帮忙!
怎么个多重纹理,能说明白些吗?或者你留个qq我们详谈!

用多重纹理
OpenGL里有多重纹理机制,
首先预先加载纹理图,以二维纹理图片为例
glBindTexture(GL_TEXTURE_2D, 纹理ID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nTEXTURESLICEWIDTH,
nTEXTURESLICEHEIGHT, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, m_ImageSliceBuffer);
然后再纹理贴图贴图,注意在绘制各面前,应先使用glBindTexture绑定指定纹理ID
参考技术A 分配6个纹理对象
对其分别设置属性
glBindTexture(0)
画第1个面
。。。
glBindTexture(5)
画第6个面

环境映射(EnvironmentMapping)的立方映射

参考技术A

立方环境映射(Cubic Environment Mapping)
立方环境映射是现在常用环境映射技术。我们知道游戏场景中经常通过在一个正方体上的六个面贴上前后左右上下六个贴图来模拟天空、宇宙等环境,称为Cubemap有的引擎中成为Skybox,立方环境映射的原理就是在游戏中所需要产生映射的物体的位置动态生成一套Cubemap,再对Cubemap进行采样生成物体表面应该反射出的周遭环境。
具体的采样方法是利用物体表面的法线来计算的,我们假设动态生成的Cubemap的正方体刚刚好包围住需要产生环境映射效果的物体,我们从摄像机也就是观察点出发同物体表面产生出的反射向量(同Phong光照模型的镜面反射中的反射向量是相同的,计算方法也相同R=2(E*N)*N-E),这个反射向量同正方体相交于一点,得到了这个点的所在面及UV坐标,采样,得到的颜色值就是我们应当看到。
立方环境映射的原理就是这样的,但是这些计算步骤并不需要我们在使用的时候过多考虑,因为从Cubemap的生成,到采样的计算,图形API已经都为我们封装好了,下面记录了在DirectX中简单的API调用流程,权作笔记。
首先需要声明Cubemap的贴图
LPDIRECT3DCUBETEXTURE9 m_pCubeMap = NULL;
然后创建Cubemap贴图
pd3dDevice->CreateCubeTexture(256,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT , &m_pCubeMap,NULL );
注意这里用到了D3DUSAGE_RENDERTARGET,也就是说我们的Cubemap需要靠RenderTarget绘制。
如果需要的话,深度缓冲也可以考虑在内。
IDirect3DSurface9* g_pDepthCube = NULL;
DXUTDeviceSettings d3dSettings = DXUTGetDeviceSettings();
pd3dDevice->CreateDepthStencilSurface( 256, 256, d3dSettings.pp.AutoDepthStencilFormat,D3DMULTISAMPLE_NONE,0,TRUE,&g_pDepthCube, NULL );
绘制函数
void RenderSceneIntoCubeMap( IDirect3DDevice9 *pd3dDevice, double fTime )

HRESULT hr;
// Cubemap使用的投影矩阵
D3DXMATRIXA16 mProj;
D3DXMatrixPerspectiveFovLH( &mProj, D3DX_PI * 0.5f, 1.0f, 0.01f, 100.0f );
LPDIRECT3DSURFACE9 pRTOld = NULL;
V( pd3dDevice->GetRenderTarget( 0, &pRTOld ) );
LPDIRECT3DSURFACE9 pDSOld = NULL;
//if( SUCCEEDED( pd3dDevice->GetDepthStencilSurface( &pDSOld ) ) )
//
// // 如果使用深度缓冲
// V( pd3dDevice->SetDepthStencilSurface( g_pDepthCube ) );
//
for( int nFace = 0; nFace < 6; ++nFace ) //依次完成Cubemap中的六个面的绘制

LPDIRECT3DSURFACE9 pSurf;
V( m_pCubeMap->GetCubeMapSurface( (D3DCUBEMAP_FACES)nFace, 0, &pSurf ) );
V( pd3dDevice->SetRenderTarget( 0, pSurf ) );
SAFE_RELEASE( pSurf );
D3DXMATRIXA16 mView = DXUTGetCubeMapViewMatrix( nFace );
V( pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER,0x000000ff, 1.0f, 0L ) );
pd3dDevice->SetTransform(D3DTS_VIEW,&mView);
pd3dDevice->SetTransform(D3DTS_PROJECTION,&mProj);
if( SUCCEEDED( pd3dDevice->BeginScene() ) )

//在这里绘制环境
pd3dDevice->EndScene();


// Restore depth-stencil buffer and render target
/*if( pDSOld )//如果使用深度缓冲

V( pd3dDevice->SetDepthStencilSurface( pDSOld ) );
SAFE_RELEASE( pDSOld );
*/
V( pd3dDevice->SetRenderTarget( 0, pRTOld ) );
SAFE_RELEASE( pRTOld );

这个绘制函数
一般在每一帧绘制场景的最开始执行,先将场景内的物体绘制在Cubemap上。
这样我们就有了可用的Cubemap,之后我们绘制需要采用环境映射的物体时,将这个Cubemap作为Texture传入Shader内,另外还需传入观察向量用于计算反射向量。
在Shader中,顶点着色器中完成反射向量的计算:
float3 vecReflect = normalize(reflect(vecEye, InNormal));
像素着色器负责采样,HLSL中已经有现成的函数可以使用,我们只需将计算所得反射向量传入即可。
Output.RGBColor = texCUBE(EnvironmentSampler, In.CubeTexcoord);
采样器EnvironmentSampler并不需要特别的设置。
texture EnvironmentMap;
samplerCUBE EnvironmentSampler = sampler_state

Texture = (EnvironmentMap);
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
;

以上是关于opengl 把纹理映射到立方体的六个面。的主要内容,如果未能解决你的问题,请参考以下文章

C++ openGl 纹理将图像映射到球体上

使用 GLUT 在立方体上的 OpenGL 多纹理映射

纹理在openGL中使用2D纹理映射3D对象

OpenGL ES纹理

Unity Shader入门精要学习笔记 - 第10章 高级纹理

OpenGL 与 C++ - 纹理