游戏开发论坛

 找回密码
 立即注册
搜索
查看: 5261|回复: 7

关于D3D内用GetConstantByName获取Shader常量句柄的问题

[复制链接]

21

主题

158

帖子

174

积分

注册会员

Rank: 2

积分
174
发表于 2010-11-24 11:53:00 | 显示全部楼层 |阅读模式
我实验的龙书上那个散射光Shader的例子

获取vector LightDirection这个常量的时候,返回的句柄总是0

我反复对照了 shader和程序里的名词一点错也没有
我改变了Shader里声名的顺序和代码里获取的顺序,值还是0
我试着自己添加其他名称的常量,获取出来也都是0


网上说 如果一个变量你不在shader中使用
就不会再ConstantTable里出现

但是我程序中有三项操作是和这个变量有关的

LightDirection.w = 0.0f;
LightDirection = mul(input.normal, ViewMatrix);
float s = dot(LightDirection, input.normal);

59

主题

984

帖子

1200

积分

金牌会员

Rank: 6Rank: 6

积分
1200
发表于 2010-11-24 13:31:00 | 显示全部楼层

Re:关于D3D内用GetConstantByName获取Shader常量句柄的问题

你把constant table里的所有变量都输出看看,名字是否和你定义的一样
好像dx会为shader变量名添加一个前缀

21

主题

158

帖子

174

积分

注册会员

Rank: 2

积分
174
 楼主| 发表于 2010-11-24 14:42:00 | 显示全部楼层

Re:关于D3D内用GetConstantByName获取Shader常量句柄的问题

谢谢clayman的建议 我试着从ConstantTable获取其中所有变量的名字
结果发现 非常诡异的一个问题

变量声明
vector LightDirection;

Main代码包含以下内容
1) LightDirection.w = 0.0f;
2) LightDirection= mul(input.normal, ViewMatrix);
3) float s = dot(LightDirection, input.normal);

以上代码实际上是从程序中输入一个LightDirection,我在Shader中对LightDirection做一些变换,然后把它用于其它运算。
如果我注释掉前两行,程序就可以正常获得LightDirection的常量句柄。
一旦我在Shader中对LightDirection做了任何修改操作(甚至是把它赋值给另一个变量,然后对那个变量进行修改),这个LightDirection就在ConstantTable中彻底消失了!

ConstantTable的常量总数,正常情况下为7,LightDirection被和谐的情况下,为6 !!

59

主题

984

帖子

1200

积分

金牌会员

Rank: 6Rank: 6

积分
1200
发表于 2010-11-24 14:57:00 | 显示全部楼层

Re:关于D3D内用GetConstantByName获取Shader常量句柄的问题

这是你的代码有问题


如果你之前的代码没有使用过LightDirection,或者说LightDirection没有在=右边出现过,而又有
LightDirection.w = 0.0f;
LightDirection= mul(input.normal, ViewMatrix);

那么LightDirection和一个局部变量是没有区别的,是通过main中的表达式取得值,并不会使用到从*程序*输入的值,编译的时候自然就优化了

21

主题

158

帖子

174

积分

注册会员

Rank: 2

积分
174
 楼主| 发表于 2010-11-24 15:28:00 | 显示全部楼层

Re:关于D3D内用GetConstantByName获取Shader常量句柄的问题

实际上我这样写的话,也会出问题。
extern vector LightDirection;
static vector _LightDir; //引入了一个静态全局变量进行实验

Main中包含的代码
        _LightDir.xyz = LightDirection.xyz;
        _LightDir.w = 0.0f;
        _LightDir = mul(input.normal, ViewMatrix);
       
        float s = dot(LightDirection, input.normal); // (1)
        //float s = dot(_LightDir, input.normal); //(2)

如果注释掉(2)的话,就没问题。
如果注释掉(1)的话,LightDirection就蒸发了。


另外我哭啊,这代码是龙书上的示例代码,示例代码都不能正常运行,叫人怎么继续研究下面的。

21

主题

158

帖子

174

积分

注册会员

Rank: 2

积分
174
 楼主| 发表于 2010-11-24 15:39:00 | 显示全部楼层

Re:关于D3D内用GetConstantByName获取Shader常量句柄的问题

更极端的例子
float s0 = dot(LightDirection, input.normal);//不使用这个s0,只是为了调用dot中包含LightDirection
float s = dot(_LightDir, input.normal);
======= 不能通过


float s0 = dot(LightDirection, input.normal);
float s = s0;
======= 可以通过


这看起来就好像,绝对不可以用_LightDir参与任何内建函数运算

59

主题

984

帖子

1200

积分

金牌会员

Rank: 6Rank: 6

积分
1200
发表于 2010-11-24 16:07:00 | 显示全部楼层

Re:关于D3D内用GetConstantByName获取Shader常量句柄的问题

呃,你没明白我的意思

这三行代码
_LightDir.xyz = LightDirection.xyz;    //optimized, redundant code
_LightDir.w = 0.0f;                       //optimized, redundant code
_LightDir = mul(input.normal, ViewMatrix);

编译后只相当于
_LightDir = mul(input.normal, ViewMatrix);

因为前两行都是冗余代码,没有任何意义,也就是说你这三行代码都不会用到LightDirection。


float s = dot(LightDirection, input.normal); // (1)
float s = dot(_LightDir, input.normal); //(2)
如果你把1注释了,也没有任何代码会用到LightDirection,所以LightDirection编译后被完全优化删除了

你6楼的例子也是一样,如果是
“不使用这个s0,只是为了调用dot中包含LightDirection”
那么同样整个语句是冗余的,没有实际用处,编译之后会优化删除

21

主题

158

帖子

174

积分

注册会员

Rank: 2

积分
174
 楼主| 发表于 2010-11-24 16:27:00 | 显示全部楼层

Re:关于D3D内用GetConstantByName获取Shader常量句柄的问题

谢谢!
我明白了!

原来事件的起因就是我把
LightDirection = mul(LightDirection , ViewMatrix);
写成了
LightDirection = mul(input.normal, ViewMatrix);

。。。。。

不过我收获很大,谢谢clayman!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-8-17 17:03

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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