C# 如何在Unity中从RenderTexture访问原始数据 问题的简短版本
我正在尝试访问Unity中的RenderTexture的内容,我一直在使用Graphics.Blit使用自己的材质绘制它C# 如何在Unity中从RenderTexture访问原始数据 问题的简短版本,c#,unity3d,framebuffer,rendertarget,C#,Unity3d,Framebuffer,Rendertarget,我正在尝试访问Unity中的RenderTexture的内容,我一直在使用Graphics.Blit使用自己的材质绘制它 Graphics.Blit (null, renderTexture, material); 我的材质成功地将一些yuv图像转换为rgb,我通过将其指定给UI元素的纹理进行了测试。结果是屏幕上显示正确的RGB图像 但是,我还需要二维码扫描仪的原始数据。我这样做就像我会访问它从一个摄像头解释。在下面的一条评论中提到,也可以从填充了Graphics.Blit的RenderTex
Graphics.Blit (null, renderTexture, material);
我的材质成功地将一些yuv图像转换为rgb,我通过将其指定给UI元素的纹理进行了测试。结果是屏幕上显示正确的RGB图像
但是,我还需要二维码扫描仪的原始数据。我这样做就像我会访问它从一个摄像头解释。在下面的一条评论中提到,也可以从填充了Graphics.Blit的RenderTexture中进行提取。但当我尝试这样做时,我的纹理只包含205的值。这是我在更新函数中直接在图形之后使用的代码。Blit调用:
RenderTexture.active = renderTexture;
texture.ReadPixels (new Rect (0, 0, width, height), 0, 0);
texture.Apply ();
RenderTexture.active = null;
将此纹理指定给同一UI元素时,它是灰色的,略微透明。查看图像值时,它们都是205
为什么这是可能的?我尝试填充的RenderTexture和Texture2D的格式可能有问题吗
完整代码
在下面,我添加了我正在使用的全部代码。变量的名称与我上面使用的略有不同,但基本相同:
/**
* This class continously converts the y and uv textures in
* YUV color space to a RGB texture, which can be used somewhere else
*/
public class YUV2RGBConverter : MonoBehaviour {
public Material yuv2rgbMat;
// Input textures, set these when they are available
[HideInInspector]
public Texture2D yTex;
[HideInInspector]
public Texture2D uvTex;
// Output, the converted textures
[HideInInspector]
public RenderTexture rgbRenderTex;
[HideInInspector]
public Texture2D rgbTex;
[HideInInspector]
public Color32[] rawRgbData;
/// Describes how often per second the image should be transferred to the CPU
public float GPUTransferRate = 1.0f;
private float timeSinceLastGPUTransfer = 0.0f;
private int width;
private int height;
/**
* Initializes the used textures
*/
void Start () {
updateSize (width, height);
}
/**
* Depending on the sizes of the texture, creating the needed textures for this class
*/
public void updateSize(int width, int height)
{
// Generate the input textures
yTex = new Texture2D(width / 4, height, TextureFormat.RGBA32, false);
uvTex = new Texture2D ((width / 2) * 2 / 4, height / 2, TextureFormat.RGBA32, false);
// Generate the output texture
rgbRenderTex = new RenderTexture(width, height, 0);
rgbRenderTex.antiAliasing = 0;
rgbTex = new Texture2D (width, height, TextureFormat.RGBA32, false);
// Set to shader
yuv2rgbMat.SetFloat("_TexWidth", width);
yuv2rgbMat.SetFloat("_TexHeight", height);
}
/**
* Sets the y and uv textures to some dummy data
*/
public void fillYUWithDummyData()
{
// Set the y tex everywhere to time rest
float colorValue = (float)Time.time - (float)((int)Time.time);
for (int y = 0; y < yTex.height; y++) {
for (int x = 0; x < yTex.width; x++) {
Color yColor = new Color (colorValue, colorValue, colorValue, colorValue);
yTex.SetPixel (x, y, yColor);
}
}
yTex.Apply ();
// Set the uv tex colors
for (int y = 0; y < uvTex.height; y++) {
for (int x = 0; x < uvTex.width; x++) {
int firstXCoord = 2 * x;
int secondXCoord = 2 * x + 1;
int yCoord = y;
float firstXRatio = (float)firstXCoord / (2.0f * (float)uvTex.width);
float secondXRatio = (float)secondXCoord / (2.0f * (float)uvTex.width);
float yRatio = (float)y / (float)uvTex.height;
Color uvColor = new Color (firstXRatio, yRatio, secondXRatio, yRatio);
uvTex.SetPixel (x, y, uvColor);
}
}
uvTex.Apply ();
}
/**
* Continuously convert y and uv texture to rgb texture with custom yuv2rgb shader
*/
void Update () {
// Draw to it with the yuv2rgb shader
yuv2rgbMat.SetTexture ("_YTex", yTex);
yuv2rgbMat.SetTexture ("_UTex", uvTex);
Graphics.Blit (null, rgbRenderTex, yuv2rgbMat);
// Only scan once per second
if (timeSinceLastGPUTransfer > 1 / GPUTransferRate) {
timeSinceLastGPUTransfer = 0;
// Fetch its pixels and set it to rgb texture
RenderTexture.active = rgbRenderTex;
rgbTex.ReadPixels (new Rect (0, 0, width, height), 0, 0);
rgbTex.Apply ();
RenderTexture.active = null;
rawRgbData = rgbTex.GetPixels32 ();
} else {
timeSinceLastGPUTransfer += Time.deltaTime;
}
}
}
/**
*此类将在中连续转换y和uv纹理
*YUV颜色空间到RGB纹理,可以在其他地方使用
*/
公共类YUV2RGB转换器:单行为{
公共材料yuv2rgbMat;
//输入纹理,在可用时设置这些纹理
[hideininstecpt]
公共纹理2d-yTex;
[hideininstecpt]
公共纹理2D uvTex;
//输出,转换的纹理
[hideininstecpt]
公共渲染器rgbRenderTex;
[hideininstecpt]
公共纹理2D rgbTex;
[hideininstecpt]
公共颜色32[]rawRgbData;
///描述每秒图像传输到CPU的频率
公共浮球GPUTransferRate=1.0f;
私有浮动时间IncelastGPutransfer=0.0f;
私有整数宽度;
私人内部高度;
/**
*初始化使用的纹理
*/
无效开始(){
更新大小(宽度、高度);
}
/**
*根据纹理的大小,为此类创建所需的纹理
*/
公共void updateSize(整数宽度、整数高度)
{
//生成输入纹理
yTex=新纹理2D(宽度/4,高度,TextureFormat.RGBA32,假);
uvTex=新纹理2D((宽度/2)*2/4,高度/2,TextureFormat.RGBA32,假);
//生成输出纹理
rgbRenderTex=新渲染纹理(宽度、高度,0);
rgbRenderTex.antiAliasing=0;
rgbTex=新纹理2d(宽度、高度、TextureFormat.RGBA32,false);
//设置为着色器
yuv2rgbMat.SetFloat(“_TexWidth”,宽度);
yuv2rgbMat.SetFloat(“_TexHeight”,高度);
}
/**
*将y和uv纹理设置为某些虚拟数据
*/
使用DummyData()填充公共空白
{
//将y-tex设置为time-rest
float colorValue=(float)Time.Time-(float)((int)Time.Time);
对于(int y=0;y1/GPUTransferRate){
TimesInclastGPutransfer=0;
//获取其像素并将其设置为rgb纹理
RenderTexture.active=rgbRenderTex;
rgbTex.ReadPixels(新的矩形(0,0,宽度,高度),0,0);
rgbTex.Apply();
RenderTexture.active=null;
rawRgbData=rgbTex.GetPixels32();
}否则{
TimesInclastGPutransfer+=Time.deltaTime;
}
}
}
好的,很抱歉我必须自己回答我的问题。解决方案非常简单:
我在此行中使用的宽度和高度属性:
rgbTex.ReadPixels (new Rect (0, 0, width, height), 0, 0);
其中未初始化,因此它们在其中0
我只需要将这些行添加到updateSize函数中:
this.width = width;
this.height = height;