我想在一个32位浮点变量中存储两个浮点值.编码将在C#中进行,而解码将在HLSL着色器中完成.
到目前为止,我发现的最佳解决方案是将编码值中的小数偏移硬连接,并将它们存储为"载波"浮点的整数和小数:
123.456 -> 12.3 and 45.6
Run Code Online (Sandbox Code Playgroud)
它无法处理负值,但没关系.
但是我想知道是否有更好的方法来做到这一点.
编辑:有关该任务的更多细节:
我正在使用Unity中的固定数据结构,其中顶点数据存储为浮点数.(Float2表示UV,float3正常,依此类推.)显然没有办法正确添加额外的数据,所以我必须在这些限制范围内工作,这就是为什么我认为这完全是一个更普遍的编码数据问题.例如,我可以牺牲二级UV数据来传输2x2额外数据通道.
目标是着色器模型3.0但我不介意解码是否在SM2.0上合理地工作.
只要它"合理",数据丢失就可以了.预期的值范围是0..64,但是当我想到它时,0..1也会很好,因为重新映射到着色器内的任何范围都很便宜.重要的是保持尽可能高的精度.负值并不重要.
我刚刚开始在DirectX 11中使用Compute着色器阶段,并且在Compute着色器中写入输出资源时遇到了一些不需要的行为.我似乎只得到零作为输出,据我的理解,这意味着已在Compute着色器中执行了越界读取.(越界写入导致无操作)
输入资源
首先,我创建一个ID3D11Buffer*输入数据.在创建用于输入Compute着色器阶段的SRV时,它将作为资源传递.如果输入数据永远不会改变,那么我们可以ID3D11Buffer*在创建SRV之后释放该对象,因为SRV将充当资源的句柄.
但是,我想每帧更新输入数据,所以我只是将缓冲区留给我处理以进行映射.
// Create a buffer to be bound as Compute Shader input (D3D11_BIND_SHADER_RESOURCE).
D3D11_BUFFER_DESC constantDataDesc;
constantDataDesc.Usage = D3D11_USAGE_DYNAMIC;
constantDataDesc.ByteWidth = sizeof(ParticleConstantData) * NUM_PARTICLES;
constantDataDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
constantDataDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
constantDataDesc.StructureByteStride = sizeof(ParticleConstantData);
constantDataDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
hr = device->CreateBuffer ( &constantDataDesc, 0, &mInputBuffer );
Run Code Online (Sandbox Code Playgroud)
使用新创建的缓冲区作为资源创建SRV
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
srvDesc.BufferEx.FirstElement = 0;
srvDesc.BufferEx.Flags = 0;
srvDesc.BufferEx.NumElements = NUM_PARTICLES;
hr = device->CreateShaderResourceView( mInputBuffer, &srvDesc, &mInputView );
Run Code Online (Sandbox Code Playgroud)
输出资源
现在我需要为Compute着色器创建一个要写入的资源.我还将创建一个系统内存版本的缓冲区来读取.我将使用ID3D11DeviceContext …
有人可以解释Flash中的Pixel Bender和Silverlight中的Pixel Shader(HLSL)在编程灵活性和运行时性能方面的差异吗?
我想知道在较新的着色器模型中是否支持从目标帧缓冲区读回像素值.我认为这在绘图管道的后期(非可编程)阶段是完成的,这使我希望这个特性可能已被添加到可编程管道中.
我知道可以绘制到纹理绑定的帧缓冲区,然后将此纹理发送到着色器,我只是希望有一种更优雅的方式来实现相同的功能.
我想知道HLSL中的那些输入和输出语义是什么?即为什么我要写那个TEXCOORD0;
struct VS_OUTPUT
{
float2 tc : TEXCOORD0;
};
Run Code Online (Sandbox Code Playgroud)
何时提供类型和名称?
我试图了解如何在着色器语言中实现传递参数.
我已经阅读了几篇文章和文档,但我仍然有些疑惑.特别是我试图理解C++函数调用的差异,特别强调性能.
HSLS,Cg和之间略有差异,GLSL但我想下划线的实现非常相似.
到目前为止我所理解的:
C++.不支持递归,因此不使用堆栈,并且大多数函数都是内联的,并且参数直接放入寄存器中.HLSL)内联,或者至少内联关键字始终受编译器(Cg)的尊重上面的考虑是对的吗?
现在2具体问题:
1)传递矩阵作为函数参数
inline float4 DoSomething(in Mat4x4 mat, in float3 vec)
{
...
}
Run Code Online (Sandbox Code Playgroud)
考虑到上面的功能,C++这将是令人讨厌的,并且肯定会更好地使用引用:const Mat4x4&.
着色器怎么样?这是一个糟糕的方法吗?我读过,例如,inout限定符可用于通过引用传递矩阵,但实际上它暗示了被调用函数修改的矩阵.
2)数量(和参数类型)是否有任何含义?例如,更好地使用具有有限参数集的函数?或者避免传递矩阵?是inout修改在这里提高性能的有效方法是什么?如果是这样,任何人都知道典型的编译器如何实现它?
3)是否有任何区别HLSL的GLSL说明吗?有人有这方面的提示吗?
我刚刚开始学习着色器/ hlsl等,所以请原谅这个可能很愚蠢的问题.
我正在关注微软的DirectX教程(教程(链接),代码(链接)).据我所知,他们将POSITION定义为浮点值的3元素数组:
// Define the input layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
Run Code Online (Sandbox Code Playgroud)
理所当然,每个顶点位置都有3个浮点值:x,y和z.但现在在查看Vertex着色器时,位置突然出现float4类型,而不是float3:
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
VS_OUTPUT VS( float4 Pos : POSITION, float4 Color : COLOR )
{
VS_OUTPUT output = (VS_OUTPUT)0;
output.Pos = mul( Pos, World );
output.Pos = mul( output.Pos, View );
output.Pos = mul( output.Pos, Projection );
output.Color = Color;
return output; …Run Code Online (Sandbox Code Playgroud) 我想在Visual Studio 2015中的C#项目中编译一个hlsl着色器文件.如果我添加了一个如下图所示的hlsl文件,我会立即获得正确的属性:
但是,当我想在我的C#项目(使用SharpDX)中执行此操作时,我没有获得这样的选项,因此无法编译为我的项目的CSO文件.
有谁知道这方面的解决方案?
我正在编写 CG 着色器,用于基于 Unity 的游戏的高级光照计算。有时需要对所有向量分量求和。有两种方法可以做到这一点:
我真的很好奇什么更快并且代码风格看起来更好。
显然,如果我们对CPU计算有同样的问题,第一种简单的方法要好得多。因为:
a) 不需要再分配一个float(1,1,1)向量
b) 无需将每个原始向量“v”分量乘以 1。
但由于我们在 GPU 上运行的着色器代码中执行此操作,因此我相信点积函数有一些很好的硬件优化,并且可能会在根本不分配的情况下转换 float3(1,1,1) 的分配。
float4 _someVector;
void surf (Input IN, inout SurfaceOutputStandard o){
float sum = _someVector.x + _someVector.y + _someVector.z + _someVector.w;
// VS
float sum2 = dot(_someVector, float4(1,1,1,1));
}
Run Code Online (Sandbox Code Playgroud) 我一直在尝试将 4 个 uint(8 位)编码为一个浮点数,以便我可以轻松地将它们与深度值一起存储在纹理中。我的代码无法正常工作,最终我发现问题归结为:
asuint(asfloat(uint(x))) 在大多数情况下返回 0,而实际上它应该返回 x。
理论上,此代码应该返回 x(其中 x 是整数),因为 x 中的位将被转换为 float,然后返回 uint,因此相同的位最终会再次被解释为 uint。但是,我发现该函数似乎返回 x 的唯一情况是 x 的位被解释为非常大的浮点数。我考虑到这可能是图形驱动程序问题,因此我在两台不同的计算机上进行了尝试,并且在两台计算机上都遇到了相同的问题。
我测试了此代码的其他几个变体,所有这些变体似乎都能正常工作。
asfloat(asuint(float(x))) = x
asuint(asint(uint(x))) = x
asuint(uint(x)) = x
唯一无法按预期工作的情况是本文中提到的第一个情况。这是一个错误,还是我做错了什么?此外,此代码正在 Unity 内部的片段着色器中运行。
hlsl ×10
shader ×4
directx ×3
c# ×2
c++ ×2
glsl ×2
cg ×1
directx-11 ×1
flash ×1
opengl ×1
performance ×1
pixel-bender ×1
pixel-shader ×1
sharpdx ×1
silverlight ×1