Unity3d 统一插件纹理是不变的

Unity3d 统一插件纹理是不变的,unity3d,webgl,game-development,Unity3d,Webgl,Game Development,我有一个复杂的问题。在unity WebGL中,加载纹理(使用LoadImage)会导致引擎冻结数毫秒,导致游戏中出现口吃,加载大纹理时更糟。这是一个已知的问题 为了避免冻结,我决定尝试让浏览器加载纹理,并将该纹理应用于游戏对象。这样就不会冻结,因为浏览器是在线程上进行冻结的 要做到这一点有点复杂,所以我基于WebGLMovieTexture的解决方案,这是资产存储中的免费资产,允许您使用内置播放器(而不是Unity的视频播放器)的浏览器播放电影,将其应用于纹理,然后应用于游戏对象。我经常使用它

我有一个复杂的问题。在unity WebGL中,加载纹理(使用LoadImage)会导致引擎冻结数毫秒,导致游戏中出现口吃,加载大纹理时更糟。这是一个已知的问题

为了避免冻结,我决定尝试让浏览器加载纹理,并将该纹理应用于游戏对象。这样就不会冻结,因为浏览器是在线程上进行冻结的

要做到这一点有点复杂,所以我基于WebGLMovieTexture的解决方案,这是资产存储中的免费资产,允许您使用内置播放器(而不是Unity的视频播放器)的浏览器播放电影,将其应用于纹理,然后应用于游戏对象。我经常使用它,而且效果很好,所以我决定用同样的方法来处理图像

要做到这一点,必须在Javascript中创建一个插件,在c#中创建该插件的接口类,然后创建一个使用该接口类的类

首先是Javascript插件,这里我只包括了重要的部分

var LibraryWebGLImageTexture = {

$imageInstances: [],

WebGLImageTextureCreate: function(url)
{
  var str = Pointer_stringify(url);
  var img = document.createElement('img');
  img.onload=function() {
      console.log("image load completed"); <<<-------------
  }
  img.style.display = 'none';
  img.src = str;
  return imageInstances.push(img) - 1;
},

WebGLImageTextureRefresh: function(img, tex)
{
  GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[tex]);
  GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, true);
  GLctx.texImage2D(GLctx.TEXTURE_2D, 0, GLctx.RGBA, GLctx.RGBA,GLctx.UNSIGNED_BYTE, imageInstances[img]);
  GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, false);
}
下面的类使用插件的上述接口创建插件实例,并将URL传递给图像。然后,它等待图像加载一小段时间,然后调用插件刷新功能将纹理传输到游戏对象

WebGLImageTexture it;   // plugin interface

void Start () {
    it = new WebGLImageTexture("http://interfacelift.com/wallpaper/previews/04194_pagview_672x420.jpg");
    gameObject.GetComponent<Renderer>().material.mainTexture = it;
    Invoke("loaded", 20); // wait for image to load then invoke this
} 


public void loaded()
{
    it.Refresh();
}

//Spin the cube

void Update () {
    transform.Rotate(new Vector3(1, 2, 3) * Time.deltaTime * 10);
}
插件刷新功能似乎在使用OpenGL,我不知道,它在刷新功能中给出了这个错误,这是使其工作的关键


有人知道如何解决此错误吗?

我认为出现此错误的唯一原因是纹理已分配给
gl.texStorage2D
,这意味着您只能使用
gl.texSubImage2D
更新纹理

gl.texStorage2D
在一次调用中分配纹理及其所有mip级别。从这一点上说,纹理的大小是无法改变的
gl.texImage2D
重新分配各个mip级别,因此您不能使用该级别更新使用
gl.texStorage2D
分配的纹理,但可以使用
gl.texSubImage2D
更新现有纹理的内容

换言之,改变这一行

GLctx.texImage2D(GLctx.TEXTURE_2D, 0, GLctx.RGBA, GLctx.RGBA,GLctx.UNSIGNED_BYTE, imageInstances[img]);
对此

GLctx.texSubImage2D(GLctx.TEXTURE_2D, 0, 0, 0, GLctx.RGBA, GLctx.UNSIGNED_BYTE, imageInstances[img]);
仅供参考,如果不等待纹理实际加载,代码将出现问题。如果用户连接速度慢,仅仅等待“一段时间”是不够的。您需要进行重构,以便在图像加载后从C#中的JavaScript获取事件,或者偶尔从游戏中轮询一次

只是猜测一下

var LibraryWebGLImageTexture = {

$imageInstances: [],

WebGLImageTextureCreate: function(url)
{
  var str = Pointer_stringify(url);
  var img = new Image();
  img.src = str;
  return imageInstances.push(img) - 1;
},

WebGLImageTextureLoaded: function(img)
{
  return imageInstances[img].complete;
},

WebGLImageTextureWidth: function(img)
{
  return imageInstances[img].width;
},

WebGLImageTextureHeight: function(img)
{
  return imageInstances[img].height;
},

WebGLImageTextureRefresh: function(img, tex)
{
  GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[tex]);
  GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, true);
  GLctx.texSubImage2D(GLctx.TEXTURE_2D, 0, 0, 0, GLctx.RGBA, GLctx.UNSIGNED_BYTE, imageInstances[img]);
  GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, false);
}
var LibraryWebGLImageTexture = {

$imageInstances: [],

WebGLImageTextureCreate: function(url)
{
  var str = Pointer_stringify(url);
  var img = new Image();
  var info = {img: img, error: false}
  img.onerror = function() {
    info.error = true;
  };
  img.src = str;
  return imageInstances.push(info) - 1;
},

WebGLImageTextureLoaded: function(img)
{
  return imageInstances[img].img.complete;
},

WebGLImageTextureError: function(img)
{
  return imageInstances[img].error;
},


WebGLImageTextureWidth: function(img)
{
  return imageInstances[img].img.width;
},

WebGLImageTextureHeight: function(img)
{
  return imageInstances[img].img.height;
},

WebGLImageTextureRefresh: function(img, tex)
{
  GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[tex]);
  GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, true);
  GLctx.texSubImage2D(GLctx.TEXTURE_2D, 0, 0, 0, GLctx.RGBA, GLctx.UNSIGNED_BYTE, imageInstances[img].img);
  GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, false);
}
我将让您确定是否要签入更新映像是否已加载,或者使用协同例程检查映像是否已加载

如果您还想检查错误,那么可能类似于

var LibraryWebGLImageTexture = {

$imageInstances: [],

WebGLImageTextureCreate: function(url)
{
  var str = Pointer_stringify(url);
  var img = new Image();
  img.src = str;
  return imageInstances.push(img) - 1;
},

WebGLImageTextureLoaded: function(img)
{
  return imageInstances[img].complete;
},

WebGLImageTextureWidth: function(img)
{
  return imageInstances[img].width;
},

WebGLImageTextureHeight: function(img)
{
  return imageInstances[img].height;
},

WebGLImageTextureRefresh: function(img, tex)
{
  GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[tex]);
  GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, true);
  GLctx.texSubImage2D(GLctx.TEXTURE_2D, 0, 0, 0, GLctx.RGBA, GLctx.UNSIGNED_BYTE, imageInstances[img]);
  GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, false);
}
var LibraryWebGLImageTexture = {

$imageInstances: [],

WebGLImageTextureCreate: function(url)
{
  var str = Pointer_stringify(url);
  var img = new Image();
  var info = {img: img, error: false}
  img.onerror = function() {
    info.error = true;
  };
  img.src = str;
  return imageInstances.push(info) - 1;
},

WebGLImageTextureLoaded: function(img)
{
  return imageInstances[img].img.complete;
},

WebGLImageTextureError: function(img)
{
  return imageInstances[img].error;
},


WebGLImageTextureWidth: function(img)
{
  return imageInstances[img].img.width;
},

WebGLImageTextureHeight: function(img)
{
  return imageInstances[img].img.height;
},

WebGLImageTextureRefresh: function(img, tex)
{
  GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[tex]);
  GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, true);
  GLctx.texSubImage2D(GLctx.TEXTURE_2D, 0, 0, 0, GLctx.RGBA, GLctx.UNSIGNED_BYTE, imageInstances[img].img);
  GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, false);
}

现在你可以检查你的轮询,如果
WebGLImageTextureError
返回true,那么你就得到了一个错误,如果
WebGLImageTextureLoaded
返回true,那么图像加载完成。

谢谢你的评论,请忽略调用,这只是为了测试,我只等了20秒,图像将在1秒内加载,因此现在应该可以进行此测试。。我对OpenGL一无所知,所以你能给出代码来解决它吗?非常感谢!谢谢,它成功了!!!这就是WebGL中LoadImage抖动的解决方案,这个问题已经存在一年多了,我有了解决方案的想法,并在5分钟内解决了它!
var LibraryWebGLImageTexture = {

$imageInstances: [],

WebGLImageTextureCreate: function(url)
{
  var str = Pointer_stringify(url);
  var img = new Image();
  var info = {img: img, error: false}
  img.onerror = function() {
    info.error = true;
  };
  img.src = str;
  return imageInstances.push(info) - 1;
},

WebGLImageTextureLoaded: function(img)
{
  return imageInstances[img].img.complete;
},

WebGLImageTextureError: function(img)
{
  return imageInstances[img].error;
},


WebGLImageTextureWidth: function(img)
{
  return imageInstances[img].img.width;
},

WebGLImageTextureHeight: function(img)
{
  return imageInstances[img].img.height;
},

WebGLImageTextureRefresh: function(img, tex)
{
  GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[tex]);
  GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, true);
  GLctx.texSubImage2D(GLctx.TEXTURE_2D, 0, 0, 0, GLctx.RGBA, GLctx.UNSIGNED_BYTE, imageInstances[img].img);
  GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, false);
}
public class WebGLImageTexture 
{
[DllImport("__Internal")]
private static extern int WebGLImageTextureCreate (string url);

[DllImport("__Internal")]
private static extern bool WebGLImageTextureLoaded (int img);

[DllImport("__Internal")]
private static extern bool WebGLImageTextureError (int img);

[DllImport("__Internal")]
private static extern int WebGLImageTextureWidth (int img);

[DllImport("__Internal")]
private static extern int WebGLImageTextureHeight (int img);

[DllImport("__Internal")]
private static extern void WebGLImageTextureRefresh (int img, int texture);

...