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