Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何将WebGL集成到使用canvas和2D context.drawImage的现有游戏中?_Javascript_Canvas_Webgl_Rendering_Game Engine - Fatal编程技术网

Javascript 如何将WebGL集成到使用canvas和2D context.drawImage的现有游戏中?

Javascript 如何将WebGL集成到使用canvas和2D context.drawImage的现有游戏中?,javascript,canvas,webgl,rendering,game-engine,Javascript,Canvas,Webgl,Rendering,Game Engine,我有一个游戏,它使用context.drawImage()将游戏对象的精灵表绘制到一个隐藏的画布中,然后复制到另一个画布(视口)。当前渲染器有一个摄影机,用于将画布的一部分复制到视图中。每个游戏对象都会添加到渲染器中的一个层中,并在渲染前按某个值x对每个帧进行排序。图层是按特定顺序绘制的,图层中的对象也是如此 因此,我有以下结构: //Renderer object var layers = [[object,object,object,object],//objects sorted acco

我有一个游戏,它使用
context.drawImage()
将游戏对象的精灵表绘制到一个隐藏的画布中,然后复制到另一个画布(视口)。当前渲染器有一个摄影机,用于将画布的一部分复制到视图中。每个游戏对象都会添加到渲染器中的一个层中,并在渲染前按某个值x对每个帧进行排序。图层是按特定顺序绘制的,图层中的对象也是如此

因此,我有以下结构:

//Renderer object
var layers = [[object,object,object,object],//objects sorted according to when they should be rendered
              [object,object,object,object],
              [object,object,object]];

//Simplified one frame render function
for(var i = 0; i < layers.length;i++){
    for(var j = 0; j < layers[i].length;j++){
        this.drawImage(layers[i][j]);
    }
}

...
//DrawImage function
this.drawImage = function(object){
    if(typeof object.currentAnimation !== "undefined"){//draw animation
        var tileId = object.currentAnimation.tileIds[object.currentAnimation.currentTile];
        var amountOfBlocksInARow = object.currentAnimation.tilesheet.width/object.currentAnimation.tileSize;
            
        var sourceX = Math.floor(tileId % amountOfBlocksInARow) *object.currentAnimation.tileSize;
        var sourceY = Math.floor(tileId / amountOfBlocksInARow) *object.currentAnimation.tileSize;
        this.canvasContext.drawImage(object.currentAnimation.tilesheet, sourceX, sourceY, object.currentAnimation.tileSize, object.currentAnimation.tileSize, object.x, object.y,object.width,object.height);
        object.currentAnimation.nextFrame();
    }else{//if theres no animation just an image then draw with object properties}

}

...
//Rest of the render function
//snap camera to its target then copy the camera to the view
this.cameraSnapToTarget();
this.viewportContext.drawImage(this.canvas, this.camera.x, this.camera.y, this.camera.width, this.camera.height, 0, 0, this.viewportCanvas.width, this.viewportCanvas.height);

//渲染器对象
var layers=[[object,object,object,object],//根据渲染时间排序的对象
[对象,对象,对象,对象],
[对象,对象,对象]];
//简化的单帧渲染功能
对于(变量i=0;i
还有这个html:

我想知道是否有一种方法可以实现WebGL,这样我就不必改变结构了。目前我已经尝试初始化webgl,制作一些缓冲区和着色器,但我似乎无法用它绘制任何东西。我遵循这一点,不知道如何设置缓冲区和着色器以从原始代码中获益。 我是否必须改变这种结构,或者可以在这种情况下实施这种结构


提前感谢您的帮助

我需要添加一些东西才能使我的代码正常工作 首先,我需要制作用于游戏对象的精灵表的纹理:

//I load all my images into an array I can search from
var imageArray = [];//global variables
var textures = [];//global variables
//and use it after defining onload like this:
imageArray.push(img);
function Animation(spritesheet,tileSize,tileIds,name = "",playOnce = false){
    this.name = name;
    this.spritesheet = spritesheet;
    this.tileSize = tileSize;
    this.tileIds = tileIds;
    this.speed = 1;
    this.currentTile = 0;
    this.playOnce = playOnce;
    this.texture;
    
    this.state = "stopped";
    
    this.setAnimationSpeed = function(speed){
        this.speed = speed;
    }
    
    this.setTextureFromImage = function(img){
        this.texture = textures[imageArray.indexOf(img)];//find the spritesheet from array of images which is indexed same as textures array texture[i] = imageArray[i] etc. 
    }
    
    this.setName = function(name){
        this.name = name;
    }
    
    this.setLoop = function (loop){
        this.loop = loop;
    }
    
    this.setSpritesheet = function (spritesheet){
        this.spritesheet = spritesheet;
    }
    
    this.setState = function(state){
        this.state = state;
    }
    
    this.getState = function(){
        return this.state;
    }
    
    this.play = function(){
        this.state = "playing";
    }
    
    this.stop = function(){
        this.state = "stopped";
    }
    
    this.nextFrame = function(){
        if(this.state == "playing"){
            if(typeof this.tileIds[this.currentTile+1] !== "undefined"){
                this.currentTile++;
            }else{
                if(this.playOnce)
                    this.setState("played");
                else
                    this.currentTile = 0;
            }
        }
    }
    this.setTextureFromImage(this.spritesheet);
}
加载所有图像后,我初始化webgl的纹理:

for(var i = 0; i < imageArray.length; i++){
    initializeTexture(imageArray[i]);
}

function initializeTexture(img){//these images are already loaded into the dom
   var tex = renderer.viewportContext.createTexture();
   renderer.viewportContext.bindTexture(renderer.viewportContext.TEXTURE_2D, tex);
            
   renderer.viewportContext.texParameteri(renderer.viewportContext.TEXTURE_2D, renderer.viewportContext.TEXTURE_WRAP_S, renderer.viewportContext.CLAMP_TO_EDGE);
   renderer.viewportContext.texParameteri(renderer.viewportContext.TEXTURE_2D, renderer.viewportContext.TEXTURE_WRAP_T, renderer.viewportContext.CLAMP_TO_EDGE);
   renderer.viewportContext.texParameteri(renderer.viewportContext.TEXTURE_2D, renderer.viewportContext.TEXTURE_MIN_FILTER, renderer.viewportContext.LINEAR);
        
   var texture = {
       width: img.width,   
       height: img.height,
       texture: tex,
                    
   };
   renderer.viewportContext.bindTexture(renderer.viewportContext.TEXTURE_2D, tex);
   renderer.viewportContext.texImage2D(renderer.viewportContext.TEXTURE_2D, 0, renderer.viewportContext.RGBA, renderer.viewportContext.RGBA, renderer.viewportContext.UNSIGNED_BYTE, img);
   textures.push(texture);//array containing one of each spritesheet texture
}
作为优化,我可以使用imageArray的索引,并在渲染时从原始纹理数组中获取纹理。 我在所有游戏对象中使用动画对象,如下所示:

this.animations = [
    new Animation(this.spritesheet,32,[0,1],"walkDown"),//walkdown
    new Animation(this.spritesheet,32,[2,3],"walkRight"),//walkright
    new Animation(this.spritesheet,32,[4,5],"walkLeft"),//walkleft
    new Animation(this.spritesheet,32,[6,7],"walkUp"),//walkup
]
最后,我可以使用以下方法渲染它们:

//Renderer
this.viewportContext = this.viewportCanvas.getContext("webgl",{ alpha: false ,premultipliedAlpha: false});
    
    
this.render = function(){//render one frame
    this.sortLayers();//can do sorting here
    this.viewportContext.viewport(0,0,this.viewportContext.canvas.width, 
    this.viewportContext.canvas.height);
    this.viewportContext.clear(this.viewportContext.COLOR_BUFFER_BIT);//clear buffers before rendering
    for(var i = 0; i < this.layerArray.length;i++){
        if(this.layerArray[i].constructor === Array){
            for(var j = 0; j < this.layerArray[i].length;j++){
                var object = this.layerArray[i][j];
                if(typeof object.currentAnimation !== "undefined"){
                    var tileId = object.currentAnimation.tileIds[object.currentAnimation.currentTile];
                    var amountOfBlocksInARow = object.currentAnimation.spritesheet.width/object.currentAnimation.tileSize;
                    var sourceX = Math.floor(tileId % amountOfBlocksInARow) *object.currentAnimation.tileSize;
                    var sourceY = Math.floor(tileId / amountOfBlocksInARow) *object.currentAnimation.tileSize;
                    this.drawImage(object.currentAnimation.texture.texture,
                        object.currentAnimation.texture.width,
                        object.currentAnimation.texture.height, 
                        sourceX, sourceY, 
                        object.currentAnimation.tileSize, 
                        object.currentAnimation.tileSize, 
                        object.x,object.y,
                        object.width,object.height);
                    }
                }
            }
        }
    }
}

this.drawImage = function(tex, texWidth, texHeight,srcX, srcY, srcWidth, srcHeight,dstX, dstY, dstWidth, dstHeight){
    if (dstX === undefined) {
        dstX = srcX;
        srcX = 0;
    }
    if (dstY === undefined) {
        dstY = srcY;
        srcY = 0;
    }
    if (srcWidth === undefined) {
        srcWidth = texWidth;
    }
    if (srcHeight === undefined) {
        srcHeight = texHeight;
    }
    if (dstWidth === undefined) {
        dstWidth = srcWidth;
        srcWidth = texWidth;
    }
    if (dstHeight === undefined) {
        dstHeight = srcHeight;
        srcHeight = texHeight;
    }
    
    this.viewportContext.enable(this.viewportContext.BLEND);
    this.viewportContext.blendFunc(this.viewportContext.SRC_ALPHA, this.viewportContext.ONE_MINUS_SRC_ALPHA);
    this.viewportContext.bindTexture(this.viewportContext.TEXTURE_2D, tex);
    
    this.viewportContext.useProgram(program);
    
    this.viewportContext.bindBuffer(this.viewportContext.ARRAY_BUFFER,positionBuffer);
    this.viewportContext.enableVertexAttribArray(positionAttributeLocation);
    this.viewportContext.vertexAttribPointer(positionAttributeLocation, 2, this.viewportContext.FLOAT, false, 0, 0);
    this.viewportContext.bindBuffer(this.viewportContext.ARRAY_BUFFER, textureCoordinateBuffer);
    this.viewportContext.enableVertexAttribArray(textureCoordinateLocation);
    this.viewportContext.vertexAttribPointer(textureCoordinateLocation, 2, this.viewportContext.FLOAT, false, 0, 0);
    
    this.matrix = m4.orthographic(0, this.viewportContext.canvas.width, this.viewportContext.canvas.height, 0, -1, 1);
    
    this.matrix = m4.translate(this.matrix,dstX,dstY,0);
    
    this.matrix = m4.scale(this.matrix, dstWidth, dstHeight, 1);
    
    this.viewportContext.uniformMatrix4fv(matrixLocation,false,this.matrix);
    
    var textureMatrix = m4.scaling(1/ texWidth, 1/texHeight, 1);
    //scaling
    
    textureMatrix = m4.translate(textureMatrix, srcX, srcY, 0);
    textureMatrix = m4.scale(textureMatrix, srcWidth, srcHeight, 1);
    
    this.viewportContext.uniformMatrix4fv(textureMatrixLocation, false, textureMatrix);
    
    this.viewportContext.drawArrays(this.viewportContext.TRIANGLES, 0, 6);
}
//渲染器
this.viewportContext=this.viewportCanvas.getContext(“webgl”,{alpha:false,premultipledalpha:false});
this.render=函数(){//渲染一帧
this.sortLayers();//可以在这里进行排序
this.viewportContext.viewport(0,0,this.viewportContext.canvas.width,
此参数为(0.viewportContext.canvas.height);
this.viewportContext.clear(this.viewportContext.COLOR_BUFFER_BIT);//渲染前清除缓冲区
for(var i=0;i