【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2932|回复: 3

改进粒子系统-动态编译Shader

[复制链接]
发表于 2008-10-23 19:02:54 | 显示全部楼层 |阅读模式
动态决定需要编译的FX代码
请教了几个朋友,最后决定用使用FX支持的宏定义解决这个问题。
根据粒子使用的发射器和效果器定义不同的宏,在FX文件中通过判断相应的宏是否定义(#ifdef…#endif)来决定是否编译某段代码。
FX代码如下:

struct VS_INPUT
{
float3 Position : POSITION;
float2 Tex0 : TEXCOORD0;
float3 Tex1 : TEXCOORD1; // UpOffset, LeftOffset, TotalTimeToLife
float3 Tex2 : TEXCOORD2; // Velocity
float3 Tex3 : TEXCOORD3; // Rotation
float3 StartDiffuse : COLOR0;
};

struct VS_OUTPUT
{
float4 Position : POSITION;
float3 Diffuse : COLOR0;
float2 Tex0 : TEXCOORD0;
float2 Tex1 : TEXCOORD1;
};

matrix matWorldViewProj; // world-view-proj matrix
float4 rightVector; // Right Vector
float4 upVector; // Up Vector
float4 time_colour; // Elasped Time, Delta Colour
float4 acceleration;

float fInitParticleWidth;
float fInitParticleHeight;

//texture textureParticle;
sampler particleSampler = sampler_state
{
//Texture = (textureParticle);

AddressU = WRAP;
AddressV = WRAP;
AddressW = WRAP;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};


#ifdef AnimationTexture
int iAnimTexSideLength;
int iAnimTexNumFrame;
float fAnimTexDuration;
#endif

#ifdef v3dScaleAffector
float fScalePerSecond;
#endif

#ifdef v3dColourImageAffector
texture textureColour;
sampler colourSampler = sampler_state
{
Texture = (textureColour);

MinFilter = Point;
MagFilter = Point;
MipFilter = Point;
};
#endif

VS_OUTPUT VS(const VS_INPUT Input)
{
VS_OUTPUT Out = (VS_OUTPUT) 0;

// Live Time = fmod( Elapsed Time, TotalTimeToLife )
float fLiveTime = fmod(time_colour.x, Input.Tex1.z);

float fParticleWidth = fInitParticleWidth;
float fParticleHeight = fInitParticleHeight;
#ifdef v3dScaleAffector
float fDeltaScale = fScalePerSecond * fLiveTime;
fParticleWidth += fDeltaScale;
fParticleHeight += fDeltaScale;
if( fParticleWidth < 0.f || fParticleHeight < 0.f )
fParticleWidth = fParticleHeight = 0.f;
#endif

// Position = right + up + pos;
float4 right = rightVector * Input.Tex1.x * fParticleWidth;
float4 up = upVector * Input.Tex1.y * fParticleHeight;
float4 Pos = float4(Input.Position,0) + right + up;


// Position = Pos + vt + 1/2*v*t*t
float4 deltaVel = mul( float4(Input.Tex2,0), fLiveTime);
#ifdef v3dLinearForceAffector
deltaVel = deltaVel + acceleration * fLiveTime * fLiveTime;
#endif
Pos = Pos + deltaVel;

Pos.w = 1.0;
Out.Position = mul( Pos, matWorldViewProj );

// color
Out.Diffuse = Input.StartDiffuse;
#ifdef v3dColourFaderAffector
Out.Diffuse.x = Input.StartDiffuse.x + time_colour.y*fLiveTime;
Out.Diffuse.y = Input.StartDiffuse.y + time_colour.z*fLiveTime;
Out.Diffuse.z = Input.StartDiffuse.z + time_colour.w*fLiveTime;
#endif

// texcoord
Out.Tex0 = Input.Tex0;
#ifdef AnimationTexture
float fAnimTexLiveTime = fmod(fLiveTime, fAnimTexDuration);
int iAnimTexCurrFrame = (fAnimTexLiveTime/fAnimTexDuration) * iAnimTexNumFrame;
int iCurrX = iAnimTexCurrFrame % iAnimTexSideLength;
int iCurrY = iAnimTexCurrFrame / iAnimTexSideLength;
float2 fAnimTexCorrdXY;
if( Input.Tex1.x < 0.f)
{
fAnimTexCorrdXY.x = (float)(iCurrX) / (float)(iAnimTexSideLength);
}
else if( Input.Tex1.x > 0.f)
{
fAnimTexCorrdXY.x = (float)(iCurrX +1)/ (float)(iAnimTexSideLength);
}

if( Input.Tex1.y < 0.f)
{
fAnimTexCorrdXY.y = (float)(iCurrY+1) / (float)(iAnimTexSideLength);
}
else if( Input.Tex1.x > 0.f)
{
fAnimTexCorrdXY.y = (float)(iCurrY) / (float)(iAnimTexSideLength);
}
Out.Tex0 = fAnimTexCorrdXY;
#endif
#ifdef v3dColourImageAffector
Out.Tex1 = float2(fLiveTime, 0.f);
#endif


#ifdef v3dRotationAffector
float fRotTexDataBase[8] = {
-0.5, 0.5,
0.5, 0.5,
-0.5,-0.5,
0.5,-0.5 };

float fRotation = Input.Tex3.x + fLiveTime * Input.Tex3.y;

float fSinRot, fCosRot;
sincos( fRotation, fSinRot, fCosRot );

float2 fRotTexCorrdXY;
int iRotTexBaseIdx = Input.Tex3.z*2;
fRotTexCorrdXY.x = (fCosRot * fRotTexDataBase[iRotTexBaseIdx]) + (fSinRot * fRotTexDataBase[iRotTexBaseIdx+1]) + 0.5;
fRotTexCorrdXY.y = (fSinRot * fRotTexDataBase[iRotTexBaseIdx]) - (fCosRot * fRotTexDataBase[iRotTexBaseIdx+1]) + 0.5;
Out.Tex0 = fRotTexCorrdXY;
#endif

return Out;
}


float4 PS_1_1( VS_OUTPUT In ) : COLOR0
{
float4 finalColour = float4( In.Diffuse, 0.f );

#ifdef v3dColourImageAffector
finalColour *= tex2D( colourSampler, In.Tex1 );
#endif

finalColour *= tex2D( particleSampler, In.Tex0 );
finalColour.w = 1.f;

return finalColour;
}

technique tec0
{
pass p0
{
VertexShader = compile vs_1_1 VS();

#ifdef v3dColourImageAffector
PixelShader = compile ps_1_1 PS_1_1();//NULL;
#else
PixelShader = NULL;
#endif
}
}
对发射器,效果器的支持程度
Shader渲染器支持的属性
1, 默认高度
2, 默认宽度
3, 最大粒子数 这里代表同时存在的粒子数
4, 粒子朝向
5, 面向摄像机的方式
6, 粒子UP向量
7, 是否是2D粒子系统
支持所有发射器
8, 支持发射器特有属性(如圆环发射器的内环大小,外环大小)
9, 角度
10, 起始颜色
11, 结束颜色
12, 方向
13, 最小生存期
14, 最大生存期
15, 最小速度
16, 最大速度
17, 位置
支持的效果器及属性
18, 颜色衰减
19, 线性外力: "外力" 指加速度a, 满足公式s = vt + 1/2*a*t*t, 受力模式不起作用
20, 旋转
21, 缩放
22, 颜色衰减图

不支持状态无关的效果器:
1, 碰撞体
2, 随机速度
3, 各种力场(直线力场,点力场)
项目改动
1, 对需要用GPU优化或需要使用GPU增强效果的粒子,美术编辑使用“Shader渲染器”的版本。
2, Shader渲染器实现版本的命名规则是在原有Billboard渲染器的文件名后面加上 "_shader",程序通过文件名区分不同的版本。
3, 在游戏中加载粒子的时候
if( (有GPU实现版本) && (显卡支持该粒子要求的VS、PS版本))
加载GPU实现版本
Else
加载CPU实现版本
截图
1, 旋转


2, 缩放,此处可以看到大部分是显卡运算



3, 纹理动画


发表于 2009-2-4 13:41:56 | 显示全部楼层

哦,你定义的宏在.cpp里吗?比如v3dColourImageAffector在.cpp里定义了,如这样的形式:#define v3dColourImageAffector

发表于 2009-4-8 19:15:50 | 显示全部楼层
是啊我也想知道&nbsp; 在程序里怎么用宏定义跟FX关联&nbsp; 能给个例子不
发表于 2009-4-28 21:14:34 | 显示全部楼层
满好的,我的程序要改进。。。还在用公告板的粒子。。。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-2-6 09:52

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表