渲染一个简单的房间

最近在看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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值