Unity3d 统一插件纹理是不变的
我有一个复杂的问题。在unity WebGL中,加载纹理(使用LoadImage)会导致引擎冻结数毫秒,导致游戏中出现口吃,加载大纹理时更糟。这是一个已知的问题 为了避免冻结,我决定尝试让浏览器加载纹理,并将该纹理应用于游戏对象。这样就不会冻结,因为浏览器是在线程上进行冻结的 要做到这一点有点复杂,所以我基于WebGLMovieTexture的解决方案,这是资产存储中的免费资产,允许您使用内置播放器(而不是Unity的视频播放器)的浏览器播放电影,将其应用于纹理,然后应用于游戏对象。我经常使用它,而且效果很好,所以我决定用同样的方法来处理图像 要做到这一点,必须在Javascript中创建一个插件,在c#中创建该插件的接口类,然后创建一个使用该接口类的类 首先是Javascript插件,这里我只包括了重要的部分Unity3d 统一插件纹理是不变的,unity3d,webgl,game-development,Unity3d,Webgl,Game Development,我有一个复杂的问题。在unity WebGL中,加载纹理(使用LoadImage)会导致引擎冻结数毫秒,导致游戏中出现口吃,加载大纹理时更糟。这是一个已知的问题 为了避免冻结,我决定尝试让浏览器加载纹理,并将该纹理应用于游戏对象。这样就不会冻结,因为浏览器是在线程上进行冻结的 要做到这一点有点复杂,所以我基于WebGLMovieTexture的解决方案,这是资产存储中的免费资产,允许您使用内置播放器(而不是Unity的视频播放器)的浏览器播放电影,将其应用于纹理,然后应用于游戏对象。我经常使用它
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);
...