渲染一个简单的房间

4 篇文章 0 订阅
1 篇文章 0 订阅

最近在看Eye2012的代码,决定一点一点转到Openframeworks里面。

那么第一步,就要建立一个房间了。


房间就是一个6面体,这个没什么,用一个 ofMesh 就可以了。

可以参考下面的代码建立一个Box

/*
		construct room mesh
	*/
	float X = dims.x;
	float Y = dims.y;
	float Z = dims.z;

	static ofVec3f verts[8] = {
		ofVec3f(-X,-Y,-Z ), ofVec3f(-X,-Y, Z ), 
		ofVec3f( X,-Y, Z ), ofVec3f( X,-Y,-Z ),
		ofVec3f(-X, Y,-Z ), ofVec3f(-X, Y, Z ), 
		ofVec3f( X, Y, Z ), ofVec3f( X, Y,-Z ) 
	};

	static GLuint vIndices[12][3] = { 
		{0,1,3}, {1,2,3},	// ceiling
		{4,7,5}, {7,6,5},	// floor
		{0,4,1}, {4,5,1},	// left
		{2,6,3}, {6,7,3},	// right
		{1,5,2}, {5,6,2},	// back
		{3,7,0}, {7,4,0}	// front
	}; 

	static ofVec3f vNormals[6] = {
		ofVec3f( 0, 1, 0 ),	// ceiling
		ofVec3f( 0,-1, 0 ),	// floor
		ofVec3f( 1, 0, 0 ),	// left	
		ofVec3f(-1, 0, 0 ),	// right
		ofVec3f( 0, 0,-1 ),	// back
		ofVec3f( 0, 0, 1 ) 	// front
	};

	static ofVec2f vTexCoords[4] = {
		ofVec2f( 0.0f, 0.0f ),
		ofVec2f( 0.0f, 1.0f ), 
		ofVec2f( 1.0f, 1.0f ), 
		ofVec2f( 1.0f, 0.0f )
	};

	// 
	static GLuint tIndices[12][3] = {
		{0,1,3}, {1,2,3},	// ceiling
		{0,1,3}, {1,2,3},	// floor
		{0,1,3}, {1,2,3},	// left
		{0,1,3}, {1,2,3},	// right
		{0,1,3}, {1,2,3},	// back
		{0,1,3}, {1,2,3}	// front
	};	

	int index = 0;
	vector<unsigned int>	indices;
	vector<ofVec3f>	posCoords;
	vector<ofVec3f>	normals;
	vector<ofVec2f>	texCoords;

	for( int i=0; i<12; i++ ){
		posCoords.push_back( verts[vIndices[i][0]] );
		posCoords.push_back( verts[vIndices[i][1]] );
		posCoords.push_back( verts[vIndices[i][2]] );
		indices.push_back( index++ );
		indices.push_back( index++ );
		indices.push_back( index++ );
		normals.push_back( vNormals[i/2] );
		normals.push_back( vNormals[i/2] );
		normals.push_back( vNormals[i/2] );
		texCoords.push_back( vTexCoords[tIndices[i][0]] );
		texCoords.push_back( vTexCoords[tIndices[i][1]] );
		texCoords.push_back( vTexCoords[tIndices[i][2]] );
	}

	mesh_.addVertices(posCoords);
	mesh_.addIndices(indices);
	mesh_.addNormals(normals);
	mesh_.addTexCoords(texCoords);

接下来就是渲染了,渲染用Shader。

首先给房间加上一些AO。

Vertex Shader ( 主要就是把 顶点位置,法线和眼向量传到片元)

uniform vec3 eyePos;

varying vec3 eyeDir;
varying vec4 vVertex;
varying vec3 vNormal;

void main()
{
	vVertex			= gl_Vertex;
	vNormal			= gl_Normal;//normalize( vec3( mMatrix * vec4( gl_Normal, 0.0 ) ) );
	
	eyeDir			= normalize( eyePos - vVertex.xyz );
	
	gl_Position		= gl_ModelViewProjectionMatrix * vVertex;
}

Fragment Shader

uniform float power;

varying vec3 eyeDir;
varying vec4 vVertex;
varying vec3 vNormal;


void main()
{
       float aoLight		= 1.0 - length( vVertex.xyz ) * ( 0.0008 + ( power * 0.001 ) );

       gl_FragColor.rgb     = vec3( aoLight );
       gl_FragColor.a		= 1.0;
}
AO的话就是以房间中心散射光线,(0.0008 + (power * 0.001 )) 就是控制半径,这样在边角就暗了,power用来控制明暗切换时,的变化。

效果如下:



接下来加一个顶灯,并且加上power的控制,实现开关灯效果

Fragment shader 加入如下代码

float aoDark		= aoLight * 0.01;
	
	float ceiling		= 0.0;
	if( vNormal.y > 0.5 ) ceiling = 1.0;// 定义法线朝下的是天花板
	
	vec3 litRoomColor	= vec3( aoLight +  ceiling  * lightPower );
	vec3 darkRoomColor	= vec3( aoDark );
	
	gl_FragColor.rgb	= mix( litRoomColor, darkRoomColor, power );

lightPower是uniform,根据power计算得出的,计算方式如下

    float p = power * 5.0f * PI;
	lightPower = cos( p ) * 0.5f + 0.5f;	
效果如下:



上图天花板和墙壁的过渡不自然,不像灯光打出来的,还需要在天花板和墙壁的地方加一个glow效果

fragment shader:

float yPer =  1.0 - clamp( abs(vVertex.y-ceilingY)/(2.*roomDims.y), 0.0, 1.0 );// 把顶点到天花板的距离作为参数计算

	float ceilingGlow	= pow( yPer, 2.0 ) * 0.35;
	ceilingGlow		+= pow( yPer, 100.0 );
	ceilingGlow		+= pow( max( yPer - 0.7, 0.0 ), 3.0 ) * 4.0;
	
	vec3 litRoomColor	= vec3( aoLight + ( ceiling + ceilingGlow ) * lightPower );


最终效果:


视频http://v.youku.com/v_show/id_XNDIzMTM4NDc2.html

git : https://github.com/Geistyp/OfwEye 

ofw 0.071

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenGL是一个跨平台的图形库,可以被用来绘制实时3D图像,并被广泛应用于游戏开发、虚拟现实、科学可视化等领域。要绘制一个房间场景,我们需要先定义房间的几何形状,然后给它们着色和添加纹理等材质属性,最后设置视角和相机位置,渲染图像。 定义几何形状:我们可以使用一系列OpenGL的基本几何形状来构建房间,例如,用立方体作为房间的主体,把屋顶和地板分别用平面多边形绘制。有了这些形状,我们就可以用OpenGL的缓存系统创建它们的顶点和着色器属性数据。 定义材质属性:绘制好几何形状后,我们需要给它们着色和添加纹理等材质属性。比如,上面提到的立方体可以用不同颜色的纹理贴在它们的表面上,地板可以用一张地砖的图案作为纹理。我们还可以设定光线反射和折射的属性,使得房间内光线的传播更加真实。 设置视角和相机位置:在定义完场景的几何形状和材质属性后,我们就要考虑如何呈现这个场景。这里,我们需要设置视角和相机位置,这些信息会影响场景显示方式。我们可以用OpenGL内置的透视投影和正交投影,来控制相机的位置、朝向、视野等信息,来呈现出不同的视角和场景。 渲染图像:当视角和相机位置设置好后,我们就可以用OpenGL的缓存和渲染系统来渲染出图像,眼前所呈现的场景就会以图像的形式呈现出来。 绘制一个房间场景并不是一件非常困难的事情。只要认真完成上述步骤,正确又有逻辑地组合出每个元素,就可以很好地呈现出一个非常真实和详细的房间场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值