SharpDX 4.0(C# WPF)动态纹理更新异常技术问询
解决SharpDX 4.0动态纹理更新时的显示异常问题
从你给出的代码片段和描述来看,纹理过宽、格式不符这类问题大多和像素格式对齐、纹理资源的创建参数或者数据更新时的内存拷贝逻辑有关,下面是几个针对性的排查和修复方向:
1. 确保像素格式与纹理创建完全匹配
这是最容易踩的坑!C#里int类型的颜色缓冲区通常是ARGB顺序,但DirectX/SharpDX默认采用BGRA格式。创建纹理时必须明确对应格式:
var textureDesc = new Texture2DDescription { Width = surfaceWidth, Height = surfaceHeight, MipLevels = 1, ArraySize = 1, Format = Format.B8G8R8A8_UNorm, // 和int类型缓冲区的BGRA格式对应 SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Dynamic, // 动态纹理必须指定这个 BindFlags = BindFlags.ShaderResource, CpuAccessFlags = CpuAccessFlags.Write, // 允许CPU写入更新 OptionFlags = ResourceOptionFlags.None }; _dynamicTexture = new Texture2D(device, textureDesc);
2. 处理纹理行对齐问题
DirectX纹理的每行字节数要求对齐到4字节倍数,哪怕你的surfaceWidth*4刚好是4的倍数,也不能直接整数组拷贝——必须按行拷贝匹配纹理的Pitch参数:
// 锁定纹理获取可写入内存区域 var dataBox = _dynamicTexture.Map(0, MapMode.WriteDiscard, MapFlags.None); try { int pitch = dataBox.RowPitch; // DirectX实际的每行字节数 int bytesPerPixel = 4; // 逐行拷贝,避免因Pitch不匹配导致数据错位 for (int y = 0; y < surfaceHeight; y++) { int sourceStartIndex = y * surfaceWidth; IntPtr destRowPtr = dataBox.DataPointer + y * pitch; Marshal.Copy(_colorBuffer, sourceStartIndex, destRowPtr, surfaceWidth); } } finally { _dynamicTexture.Unmap(0); }
如果直接整数组拷贝,当Pitch不等于surfaceWidth*4时,后续行的数据会错位,视觉上就表现为纹理过宽。
3. 转换第三方库的颜色格式
如果第三方库输出的是RGBA顺序的颜色,需要转成SharpDX要求的BGRA格式,不然会出现颜色颠倒的问题:
// 遍历缓冲区转换RGBA到BGRA for (int i = 0; i < _colorBuffer.Length; i++) { int rgba = _colorBuffer[i]; int b = (rgba >> 16) & 0xFF; int g = (rgba >> 8) & 0xFF; int r = rgba & 0xFF; int a = (rgba >> 24) & 0xFF; _colorBuffer[i] = (a << 24) | (r << 16) | (g << 8) | b; }
能让第三方库直接输出BGRA格式的话,就省去转换开销。
4. 检查Shader采样器设置
如果纹理还是显示异常,看看Shader里的采样器是否用了错误的寻址模式,比如Wrap模式会导致纹理重复拉伸:
SamplerState samplerLinear { Filter = MIN_MAG_MIP_LINEAR; AddressU = Clamp; AddressV = Clamp; // 用Clamp避免超出纹理范围的拉伸 };
内容的提问来源于stack exchange,提问作者Dan




