Mon laboratoire se trouve dans ce topic.
Topic : « [OFFICIEL] Je fais des jeux webGL »
Pour l'instant j'ai fait un test d'affichage de hapistes.
http://punkcoders.free.fr/glbm/#
Je vais maintenant tester les limitations de mon moteur graphique sur smartphone.
http://punkcoders.free.fr/glbm/#
Je vais maintenant tester les limitations de mon moteur graphique sur smartphone.
La contrainte web+smartphone m'oblige à faire des jeux à budget français de la CAF.
Pour ceux que la programmation intéresse (bon je rêve pas trop on est sur avn) voilà comment on affiche des hapistes:
// -----------------------------------------------------------------------------
// CLASS DECLARATION
// -----------------------------------------------------------------------------
function PPU_SpritesLayer( tilesheetTexture, numSprites )
{
this.build( tilesheetTexture, numSprites );
return this;
}
// -----------------------------------------------------------------------------
// STATIC PROPS
// -----------------------------------------------------------------------------
// context
PPU_SpritesLayer.CONTEXT3D = null;
PPU_SpritesLayer.CRASHED = false;
PPU_SpritesLayer.SCREEN_WIDTH = 1;
PPU_SpritesLayer.SCREEN_HEIGHT = 1;
// static initialized
PPU_SpritesLayer.INITIALIZED = false;
// instance index
PPU_SpritesLayer.NUM_INSTANCES = 0;
// tilesheet dimensions
// for the moment we use fixed dimensions, GBA format.
// multi-resolution will be a later work and should impact only tilesheets
PPU_SpritesLayer.TILESHEET_WIDTH = 128, PPU_SpritesLayer.TILESHEET_HEIGHT = 128;
// vertex shader (for the moment, the same as tilemapLayer, but will be modified)
PPU_SpritesLayer.VERTEX_SHADER_SOURCE = `
attribute vec4 aVertexPosition;
attribute vec2 aTilesheetTextureCoord;
attribute vec2 aSpritesmapTextureCoord;
varying highp vec2 vTilesheetTextureCoord;
varying highp vec2 vSpritesmapTextureCoord;
void main(void) {
gl_Position = aVertexPosition;
vTilesheetTextureCoord = aTilesheetTextureCoord;
vSpritesmapTextureCoord = aSpritesmapTextureCoord;
}
`;
PPU_SpritesLayer.VERTEX_SHADER_ID = 0;
// fragment shader
PPU_SpritesLayer.FRAGMENT_SHADER_SOURCE = `
varying highp vec2 vTilesheetTextureCoord;
varying highp vec2 vSpritesmapTextureCoord;
uniform sampler2D uTilesheetSampler;
uniform sampler2D uTilemapSampler;
uniform sampler2D uPaletteSampler;
const highp float c05 = 0.5;
const highp float c255 = 255.0 ;
const highp float c256 = 256.0 ;
highp vec4 tile;
highp float sheetTexCoordX;
highp float sheetTexCoordY;
highp vec4 colorIndex;
void main(void) {
// get cell info in 64*32 tilemap
tile = texture2D( uTilemapSampler, vSpritesmapTextureCoord );
// get the color index in 16*16 tileSheet
sheetTexCoordX = vTilesheetTextureCoord.x + (tile.r*c255+c05)/c256 ;
sheetTexCoordY = vTilesheetTextureCoord.y + (tile.g*c255+c05)/c256 ;
colorIndex = texture2D( uTilesheetSampler, vec2( ( -2.0 * tile.a + 1.0 )* sheetTexCoordX , sheetTexCoordY ) );
// get the color in the 256x256 palette
gl_FragColor = texture2D( uPaletteSampler, vec2( (colorIndex.a*c255+c05)/c256, (tile.b*c255+c05)/c256 ) );
}
`;
PPU_SpritesLayer.FRAGMENT_SHADER_ID = 0;
// shader program
PPU_SpritesLayer.SHADER_PROGRAM_ID = 0;
// shader locations
PPU_SpritesLayer.XY_ATTRIB_LOCATION = 0;
PPU_SpritesLayer.TILESHEET_UV_ATTRIB_LOCATION = 0;
PPU_SpritesLayer.SPRITESMAP_UV_ATTRIB_LOCATION = 0;
PPU_SpritesLayer.TILESHEET_TEXTURE_UNIFORM_LOCATION = 0;
PPU_SpritesLayer.SPRITESMAP_TEXTURE_UNIFORM_LOCATION = 0;
PPU_SpritesLayer.PALETTE_TEXTURE_UNIFORM_LOCATION = 0;
// -----------------------------------------------------------------------------
// STATIC METHODS
// -----------------------------------------------------------------------------
PPU_SpritesLayer.Init = function (gl, screenWidth, screenHeight)
{
PPU_SpritesLayer.CONTEXT3D = gl;
PPU_SpritesLayer.SCREEN_WIDTH = screenWidth; // avoid spaghetti, use modular classes
PPU_SpritesLayer.SCREEN_HEIGHT = screenHeight;
console.log('PPU_SpritesLayer static shader compilation -----------------');
// compile vertex shader
PPU_SpritesLayer.VERTEX_SHADER_ID = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(PPU_SpritesLayer.VERTEX_SHADER_ID, PPU_SpritesLayer.VERTEX_SHADER_SOURCE);
gl.compileShader(PPU_SpritesLayer.VERTEX_SHADER_ID);
// compile error
if (!gl.getShaderParameter(PPU_SpritesLayer.VERTEX_SHADER_ID, gl.COMPILE_STATUS)) {
alert('PPU_SpritesLayer compile vertex shader error: ' + gl.getShaderInfoLog(PPU_SpritesLayer.VERTEX_SHADER_ID));
gl.deleteShader(PPU_SpritesLayer.VERTEX_SHADER_ID); // AJOUTER CA DANS LE CPP !!!
PPU_SpritesLayer.CRASHED = true;
return false;
} else
{
console.log("PPU_SpritesLayer vertex shader compiled.");
}
// compile fragment shader
PPU_SpritesLayer.FRAGMENT_SHADER_ID = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(PPU_SpritesLayer.FRAGMENT_SHADER_ID, PPU_SpritesLayer.FRAGMENT_SHADER_SOURCE);
gl.compileShader(PPU_SpritesLayer.FRAGMENT_SHADER_ID);
// compile error
if (!gl.getShaderParameter(PPU_SpritesLayer.FRAGMENT_SHADER_ID, gl.COMPILE_STATUS)) {
alert('PPU_SpritesLayer compile fragment shader error: ' + gl.getShaderInfoLog(PPU_SpritesLayer.FRAGMENT_SHADER_ID));
gl.deleteShader(PPU_SpritesLayer.FRAGMENT_SHADER_ID); // AJOUTER CA DANS LE CPP !!!
PPU_SpritesLayer.CRASHED = true;
return false;
} else
{
console.log("PPU_SpritesLayer fragment shader compiled");
}
// link the program shader
PPU_SpritesLayer.SHADER_PROGRAM_ID = gl.createProgram();
gl.attachShader(PPU_SpritesLayer.SHADER_PROGRAM_ID, PPU_SpritesLayer.VERTEX_SHADER_ID);
gl.attachShader(PPU_SpritesLayer.SHADER_PROGRAM_ID, PPU_SpritesLayer.FRAGMENT_SHADER_ID);
gl.linkProgram(PPU_SpritesLayer.SHADER_PROGRAM_ID);
// compile error
if (!gl.getProgramParameter(PPU_SpritesLayer.SHADER_PROGRAM_ID, gl.LINK_STATUS)) {
alert('PPU_SpritesLayer link shaders program error: ' + gl.getProgramInfoLog(PPU_SpritesLayer.SHADER_PROGRAM_ID));
gl.deleteShader(PPU_SpritesLayer.VERTEX_SHADER_ID); // AJOUTER CA DANS LE CPP !!!
gl.deleteShader(PPU_SpritesLayer.FRAGMENT_SHADER_ID); // AJOUTER CA DANS LE CPP !!!
PPU_SpritesLayer.CRASHED = true;
return false;
} else
{
console.log("PPU_SpritesLayer shader programs linked");
}
// shader locations
PPU_SpritesLayer.XY_ATTRIB_LOCATION = gl.getAttribLocation(PPU_SpritesLayer.SHADER_PROGRAM_ID, 'aVertexPosition');
PPU_SpritesLayer.TILESHEET_UV_ATTRIB_LOCATION = gl.getAttribLocation(PPU_SpritesLayer.SHADER_PROGRAM_ID, 'aTilesheetTextureCoord');
PPU_SpritesLayer.SPRITESMAP_UV_ATTRIB_LOCATION = gl.getAttribLocation(PPU_SpritesLayer.SHADER_PROGRAM_ID, 'aSpritesmapTextureCoord');
PPU_SpritesLayer.TILESHEET_TEXTURE_UNIFORM_LOCATION = gl.getUniformLocation(PPU_SpritesLayer.SHADER_PROGRAM_ID, 'uTilesheetSampler');
PPU_SpritesLayer.SPRITESMAP_TEXTURE_UNIFORM_LOCATION = gl.getUniformLocation(PPU_SpritesLayer.SHADER_PROGRAM_ID, 'uTilemapSampler');
PPU_SpritesLayer.PALETTE_TEXTURE_UNIFORM_LOCATION = gl.getUniformLocation(PPU_SpritesLayer.SHADER_PROGRAM_ID, 'uPaletteSampler');
// bool
PPU_SpritesLayer.INITIALIZED = true;
};
PPU_SpritesLayer.ShutDown = function ()
{
if (!PPU_SpritesLayer.CRASHED && PPU_SpritesLayer.INITIALIZED)
{
const gl = PPU_SpritesLayer.CONTEXT3D;
gl.detachShader(PPU_SpritesLayer.SHADER_PROGRAM_ID,PPU_SpritesLayer.VERTEX_SHADER_ID);
gl.detachShader(PPU_SpritesLayer.SHADER_PROGRAM_ID,PPU_SpritesLayer.FRAGMENT_SHADER_ID);
gl.deleteShader(PPU_SpritesLayer.VERTEX_SHADER_ID);
gl.deleteShader(PPU_SpritesLayer.FRAGMENT_SHADER_ID);
console.log("PPU_SpritesLayer shaders deleted");
}
// bool
PPU_SpritesLayer.INITIALIZED = false;
};
// -----------------------------------------------------------------------------
// INSTANCE PROPS
// -----------------------------------------------------------------------------
// instance index
PPU_SpritesLayer.prototype.m_instanceIndex = 0;
// num sprites
PPU_SpritesLayer.prototype.m_numSprites = 0;
// vertex arrays & buffers
PPU_SpritesLayer.prototype.m_sprites_YX = null; //new Float32Array( 8 * this.m_numSprites ); // updated every frame, from uv * matrix
PPU_SpritesLayer.prototype.m_sprites_tilesheet_UV = null; //new Float32Array( 8 * this.m_numSprites ); // updated at init. default 0.0-1.0
PPU_SpritesLayer.prototype.m_spritemap_UV = null; //new Float32Array( 8 * this.m_numSprites ); // theorically updated at init
PPU_SpritesLayer.prototype.m_sprites_indexes = null; //new Uint16Array( 6 * this.m_numSprites );
PPU_SpritesLayer.prototype.m_sprites_XY_buffer = null;
PPU_SpritesLayer.prototype.m_sprites_tileSheet_UV_buffer = null;
PPU_SpritesLayer.prototype.m_spritemap_UV_buffer = null; // all at 0.5 centered on pixels
PPU_SpritesLayer.prototype.m_sprites_indexes_buffer = null;
// arrays & textures for spritemap, palette and scanlines
PPU_SpritesLayer.prototype.m_palette_array = null ; //new Uint8Array( 4 * 16 * 16 );
PPU_SpritesLayer.prototype.m_spritemap_array = null ; //new Uint8Array( 4 * this.m_numSprites );
PPU_SpritesLayer.prototype.m_tileSheet_texture = null; // managed elsewhere
PPU_SpritesLayer.prototype.m_palette_texture = null;
PPU_SpritesLayer.prototype.m_spritemap_texture = null;
// -----------------------------------------------------------------------------
// INSTANCE METHODS
// -----------------------------------------------------------------------------
// build-delete
PPU_SpritesLayer.prototype.build = function( tilesheetTexture, numSprites )
{
// do nothing if not init
if (!PPU_SpritesLayer.INITIALIZED)
{
return null;
}
// instance index
this.m_instanceIndex = PPU_SpritesLayer.NUM_INSTANCES;
PPU_SpritesLayer.NUM_INSTANCES++;
// cache context
const gl = PPU_SpritesLayer.CONTEXT3D;
// args
this.m_numSprites = numSprites;
// alloc CPU arrays and GPU vertex buffers ---------------------------------
// dimension sprites vertex arrays
this.m_sprites_YX = new Float32Array( 8 * this.m_numSprites ); // updated every frame, from uv * matrix
this.m_sprites_tilesheet_UV = new Float32Array( 8 * this.m_numSprites ); // updated at init. default 0.0-1.0
this.m_spritemap_UV = new Float32Array( 8 * this.m_numSprites ); // theorically updated at init, col-row offsets are in spritemap texture
this.m_sprites_indexes = new Uint16Array( 6 * this.m_numSprites );
// cache arrays
var tshUV = this.m_sprites_tilesheet_UV;
var mapUV = this.m_spritemap_UV;
var indxs = this.m_sprites_indexes;
// compute initial values
for ( var iSp = 0; iSp < this.m_numSprites; iSp++ )
{
// uv coords in tileSheet
var it = iSp*8;
// 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0
tshUV[ it + 0 ] = 0.0/16.0 ; tshUV[ it + 1 ] = 1.0/16.0 ;
tshUV[ it + 2 ] = 1.0/16.0 ; tshUV[ it + 3 ] = 1.0/16.0 ;
tshUV[ it + 4 ] = 1.0/16.0 ; tshUV[ it + 5 ] = 0.0/16.0 ;
tshUV[ it + 6 ] = 0.0/16.0 ; tshUV[ it + 7 ] = 0.0/16.0 ;
// uv coords in spriteemap 1-dimension
var im = iSp * 8;
for ( var i=0; i<4; i++ )
{
mapUV[ im + i*2 + 0 ] = ( iSp + 0.5 ) / this.m_numSprites ;
mapUV[ im + i*2 + 1 ] = 0.5 ;
}
// indexes
var ii = iSp * 6;
indxs[ ii + 0 ] = 0 + 4*iSp;
indxs[ ii + 1 ] = 1 + 4*iSp;
indxs[ ii + 2 ] = 2 + 4*iSp;
indxs[ ii + 3 ] = 0 + 4*iSp;
indxs[ ii + 4 ] = 2 + 4*iSp;
indxs[ ii + 5 ] = 3 + 4*iSp;
}
// sprites GPU verts buffers
this.m_sprites_XY_buffer = gl.createBuffer(); // updated at runtime only
this.m_sprites_tileSheet_UV_buffer = gl.createBuffer(); // defaut 0.0 - 1.0
gl.bindBuffer(gl.ARRAY_BUFFER, this.m_sprites_tileSheet_UV_buffer );
gl.bufferData(gl.ARRAY_BUFFER, this.m_sprites_tilesheet_UV, gl.STATIC_DRAW); // will be updated at init later
// for these two ones i could discard array member, we'll see
this.m_spritemap_UV_buffer = gl.createBuffer(); // .5 everywhere, never updated
gl.bindBuffer(gl.ARRAY_BUFFER, this.m_spritemap_UV_buffer );
gl.bufferData(gl.ARRAY_BUFFER, this.m_spritemap_UV, gl.STATIC_DRAW);
this.m_sprites_indexes_buffer = gl.createBuffer(); // never updated
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.m_sprites_indexes_buffer );
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.m_sprites_indexes, gl.STATIC_DRAW); // static buffer, won't be streamed
console.log(" PPU_SpritesLayer instance "+this.m_instanceIndex+" vertices buffers created");
// alloc CPU arrays and GPU textures ---------------------------------------
this.m_tileSheet_texture = tilesheetTexture; // managed elsewhere
this.m_palette_array = new Uint8Array( 4 * 16 * 16 );
this.m_palette_texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.m_palette_texture);
// oldschool rendering
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
// initialize data (may be removed)
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16 , 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.m_palette_array);
this.m_spritemap_array = new Uint8Array( 4 * this.m_numSprites );
this.m_spritemap_texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.m_spritemap_texture);
// oldschool rendering
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
// initialize data (may be removed)
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.m_numSprites, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.m_spritemap_array);
console.log(" PPU_SpritesLayer instance "+this.m_instanceIndex+" textures created");
};
PPU_SpritesLayer.prototype.delete = function()
{
// do nothing if not init
if (!PPU_SpritesLayer.INITIALIZED)
{
console.log('TilesheetTester not initialized');
return null;
}
// cache context
const gl = PPU_SpritesLayer.CONTEXT3D;
// delete arrays and textures ----------------------------------------------
gl.deleteTexture(this.m_palette_texture);
this.m_palette_array = null;
gl.deleteTexture(this.m_spritemap_texture);
this.m_spritemap_array = null;
console.log(" PPU_SpritesLayer instance "+this.m_instanceIndex+" textures deleted");
// delete verts buffers ----------------------------------------------------
gl.deleteBuffer(this.m_sprites_XY_buffer);
this.m_sprites_YX = null;
gl.deleteBuffer(this.m_sprites_tileSheet_UV_buffer);
this.m_sprites_tilesheet_UV = null;
gl.deleteBuffer(this.m_spritemap_UV_buffer);
this.m_spritemap_UV = null;
gl.deleteBuffer(this.m_sprites_indexes_buffer);
this.m_sprites_indexes = null;
console.log(" PPU_SpritesLayer instance "+this.m_instanceIndex+" vertices buffers deleted");
};
// update sprites and palette
PPU_SpritesLayer.prototype.setColor = function ( y, x, r, g, b, a)
{
// voir si ce bordel là est optimisable avec des array 32 (là y'a dla doc webgl à fouiller)
const addr = ( (x&15) | ((y&15)<<4) ) * 4;
let pa = this.m_palette_array;
pa[ addr + 0 ] = r ;
pa[ addr + 1 ] = g ;
pa[ addr + 2 ] = b ;
pa[ addr + 3 ] = a ;
};
PPU_SpritesLayer.prototype.setSprite = function ( index, visible, x, y, indexAscii, paletteY, flipX )
{
x = Math.floor(x); // round coords
y = Math.floor(y);
let xys = this.m_sprites_YX;
const uvs = this.m_sprites_tilesheet_UV;
const iF = index * 8; // index first double
// hide unactive sprite and return
if ( ! visible )
{
for ( let i=0; i<8; i++ )
{
xys[ iF + i ] = -1024 ; // x/y outField
}
return;
}
// compute the pseudo-matrix
const imgW = 128.0, imgH = 128.0; // x y coordinates based on sheet dimensions
const matw = imgW / PPU_SpritesLayer.SCREEN_WIDTH * 2 ;
const math = -imgH / PPU_SpritesLayer.SCREEN_HEIGHT * 2 ;
const matx = x * matw / imgW;
const maty = y * math / imgH;
// tileSheet UV coords are converted to XY coords with "matrix"
for ( let i=0; i<4; i++ )
{
const ix = iF + i*2;
xys[ ix+0 ] = uvs[ ix+0 ] * matw + matx ; // x
xys[ ix+1 ] = uvs[ ix+1 ] * math + maty ; // y
}
// update pixel data in cellList
let colInSheet = indexAscii & 15 ;
if ( flipX )
{
colInSheet = 127 - colInSheet;
}
let rowInSheet = Math.floor( (indexAscii & 255) / 16 );
let colOffset = colInSheet & 15;
let rowOffset = rowInSheet & 15;
let map = this.m_spritemap_array;
const c = index % this.m_numSprites;
map[ 4*c + 0 ] = colOffset << 4 ; // 255->1.0, so 16*16
map[ 4*c + 1 ] = rowOffset << 4 ;
map[ 4*c + 2 ] = paletteY << 4 ;
map[ 4*c + 3 ] = flipX * 255 ; // glsl reads 0.0 / 1.0
};
// drawcall render
PPU_SpritesLayer.prototype.drawCall = function()
{
// cache context
const gl = PPU_SpritesLayer.CONTEXT3D;
// CPU->GPU STREAM PHASE ----------------------------------------------------
// update textures
gl.bindTexture(gl.TEXTURE_2D, this.m_spritemap_texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.m_numSprites, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.m_spritemap_array);
gl.bindTexture(gl.TEXTURE_2D, this.m_palette_texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.m_palette_array);
// update vertices
gl.bindBuffer(gl.ARRAY_BUFFER, this.m_sprites_XY_buffer);
gl.bufferData(gl.ARRAY_BUFFER, this.m_sprites_YX, gl.STATIC_DRAW);
// DRAW PHASE --------------------------------------------------------------
// bind vertex buffers
gl.bindBuffer(gl.ARRAY_BUFFER, this.m_sprites_XY_buffer);
gl.vertexAttribPointer(PPU_SpritesLayer.XY_ATTRIB_LOCATION, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(PPU_SpritesLayer.XY_ATTRIB_LOCATION);
gl.bindBuffer(gl.ARRAY_BUFFER, this.m_sprites_tileSheet_UV_buffer);
gl.vertexAttribPointer(PPU_SpritesLayer.TILESHEET_UV_ATTRIB_LOCATION, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(PPU_SpritesLayer.TILESHEET_UV_ATTRIB_LOCATION);
gl.bindBuffer(gl.ARRAY_BUFFER, this.m_spritemap_UV_buffer);
gl.vertexAttribPointer(PPU_SpritesLayer.SPRITESMAP_UV_ATTRIB_LOCATION, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(PPU_SpritesLayer.SPRITESMAP_UV_ATTRIB_LOCATION);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.m_sprites_indexes_buffer);
// select shader program (revoir si c'est dans le bon ordre)
gl.useProgram(PPU_SpritesLayer.SHADER_PROGRAM_ID);
// bind textures
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this.m_tileSheet_texture);
gl.uniform1i(PPU_SpritesLayer.TILESHEET_TEXTURE_UNIFORM_LOCATION, 0);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, this.m_spritemap_texture);
gl.uniform1i(PPU_SpritesLayer.SPRITESMAP_TEXTURE_UNIFORM_LOCATION, 1);
gl.activeTexture(gl.TEXTURE2);
gl.bindTexture(gl.TEXTURE_2D, this.m_palette_texture);
gl.uniform1i(PPU_SpritesLayer.PALETTE_TEXTURE_UNIFORM_LOCATION, 2);
// draw triangles
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.drawElements(gl.TRIANGLES, 6 * this.m_numSprites, gl.UNSIGNED_SHORT, 0);
gl.disable(gl.BLEND);
};
// -----------------------------------------------------------------------------
// CLASS DECLARATION
// -----------------------------------------------------------------------------
function PPU_SpritesLayer( tilesheetTexture, numSprites )
{
this.build( tilesheetTexture, numSprites );
return this;
}
// -----------------------------------------------------------------------------
// STATIC PROPS
// -----------------------------------------------------------------------------
// context
PPU_SpritesLayer.CONTEXT3D = null;
PPU_SpritesLayer.CRASHED = false;
PPU_SpritesLayer.SCREEN_WIDTH = 1;
PPU_SpritesLayer.SCREEN_HEIGHT = 1;
// static initialized
PPU_SpritesLayer.INITIALIZED = false;
// instance index
PPU_SpritesLayer.NUM_INSTANCES = 0;
// tilesheet dimensions
// for the moment we use fixed dimensions, GBA format.
// multi-resolution will be a later work and should impact only tilesheets
PPU_SpritesLayer.TILESHEET_WIDTH = 128, PPU_SpritesLayer.TILESHEET_HEIGHT = 128;
// vertex shader (for the moment, the same as tilemapLayer, but will be modified)
PPU_SpritesLayer.VERTEX_SHADER_SOURCE = `
attribute vec4 aVertexPosition;
attribute vec2 aTilesheetTextureCoord;
attribute vec2 aSpritesmapTextureCoord;
varying highp vec2 vTilesheetTextureCoord;
varying highp vec2 vSpritesmapTextureCoord;
void main(void) {
gl_Position = aVertexPosition;
vTilesheetTextureCoord = aTilesheetTextureCoord;
vSpritesmapTextureCoord = aSpritesmapTextureCoord;
}
`;
PPU_SpritesLayer.VERTEX_SHADER_ID = 0;
// fragment shader
PPU_SpritesLayer.FRAGMENT_SHADER_SOURCE = `
varying highp vec2 vTilesheetTextureCoord;
varying highp vec2 vSpritesmapTextureCoord;
uniform sampler2D uTilesheetSampler;
uniform sampler2D uTilemapSampler;
uniform sampler2D uPaletteSampler;
const highp float c05 = 0.5;
const highp float c255 = 255.0 ;
const highp float c256 = 256.0 ;
highp vec4 tile;
highp float sheetTexCoordX;
highp float sheetTexCoordY;
highp vec4 colorIndex;
void main(void) {
// get cell info in 64*32 tilemap
tile = texture2D( uTilemapSampler, vSpritesmapTextureCoord );
// get the color index in 16*16 tileSheet
sheetTexCoordX = vTilesheetTextureCoord.x + (tile.r*c255+c05)/c256 ;
sheetTexCoordY = vTilesheetTextureCoord.y + (tile.g*c255+c05)/c256 ;
colorIndex = texture2D( uTilesheetSampler, vec2( ( -2.0 * tile.a + 1.0 )* sheetTexCoordX , sheetTexCoordY ) );
// get the color in the 256x256 palette
gl_FragColor = texture2D( uPaletteSampler, vec2( (colorIndex.a*c255+c05)/c256, (tile.b*c255+c05)/c256 ) );
}
`;
PPU_SpritesLayer.FRAGMENT_SHADER_ID = 0;
// shader program
PPU_SpritesLayer.SHADER_PROGRAM_ID = 0;
// shader locations
PPU_SpritesLayer.XY_ATTRIB_LOCATION = 0;
PPU_SpritesLayer.TILESHEET_UV_ATTRIB_LOCATION = 0;
PPU_SpritesLayer.SPRITESMAP_UV_ATTRIB_LOCATION = 0;
PPU_SpritesLayer.TILESHEET_TEXTURE_UNIFORM_LOCATION = 0;
PPU_SpritesLayer.SPRITESMAP_TEXTURE_UNIFORM_LOCATION = 0;
PPU_SpritesLayer.PALETTE_TEXTURE_UNIFORM_LOCATION = 0;
// -----------------------------------------------------------------------------
// STATIC METHODS
// -----------------------------------------------------------------------------
PPU_SpritesLayer.Init = function (gl, screenWidth, screenHeight)
{
PPU_SpritesLayer.CONTEXT3D = gl;
PPU_SpritesLayer.SCREEN_WIDTH = screenWidth; // avoid spaghetti, use modular classes
PPU_SpritesLayer.SCREEN_HEIGHT = screenHeight;
console.log('PPU_SpritesLayer static shader compilation -----------------');
// compile vertex shader
PPU_SpritesLayer.VERTEX_SHADER_ID = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(PPU_SpritesLayer.VERTEX_SHADER_ID, PPU_SpritesLayer.VERTEX_SHADER_SOURCE);
gl.compileShader(PPU_SpritesLayer.VERTEX_SHADER_ID);
// compile error
if (!gl.getShaderParameter(PPU_SpritesLayer.VERTEX_SHADER_ID, gl.COMPILE_STATUS)) {
alert('PPU_SpritesLayer compile vertex shader error: ' + gl.getShaderInfoLog(PPU_SpritesLayer.VERTEX_SHADER_ID));
gl.deleteShader(PPU_SpritesLayer.VERTEX_SHADER_ID); // AJOUTER CA DANS LE CPP !!!
PPU_SpritesLayer.CRASHED = true;
return false;
} else
{
console.log("PPU_SpritesLayer vertex shader compiled.");
}
// compile fragment shader
PPU_SpritesLayer.FRAGMENT_SHADER_ID = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(PPU_SpritesLayer.FRAGMENT_SHADER_ID, PPU_SpritesLayer.FRAGMENT_SHADER_SOURCE);
gl.compileShader(PPU_SpritesLayer.FRAGMENT_SHADER_ID);
// compile error
if (!gl.getShaderParameter(PPU_SpritesLayer.FRAGMENT_SHADER_ID, gl.COMPILE_STATUS)) {
alert('PPU_SpritesLayer compile fragment shader error: ' + gl.getShaderInfoLog(PPU_SpritesLayer.FRAGMENT_SHADER_ID));
gl.deleteShader(PPU_SpritesLayer.FRAGMENT_SHADER_ID); // AJOUTER CA DANS LE CPP !!!
PPU_SpritesLayer.CRASHED = true;
return false;
} else
{
console.log("PPU_SpritesLayer fragment shader compiled");
}
// link the program shader
PPU_SpritesLayer.SHADER_PROGRAM_ID = gl.createProgram();
gl.attachShader(PPU_SpritesLayer.SHADER_PROGRAM_ID, PPU_SpritesLayer.VERTEX_SHADER_ID);
gl.attachShader(PPU_SpritesLayer.SHADER_PROGRAM_ID, PPU_SpritesLayer.FRAGMENT_SHADER_ID);
gl.linkProgram(PPU_SpritesLayer.SHADER_PROGRAM_ID);
// compile error
if (!gl.getProgramParameter(PPU_SpritesLayer.SHADER_PROGRAM_ID, gl.LINK_STATUS)) {
alert('PPU_SpritesLayer link shaders program error: ' + gl.getProgramInfoLog(PPU_SpritesLayer.SHADER_PROGRAM_ID));
gl.deleteShader(PPU_SpritesLayer.VERTEX_SHADER_ID); // AJOUTER CA DANS LE CPP !!!
gl.deleteShader(PPU_SpritesLayer.FRAGMENT_SHADER_ID); // AJOUTER CA DANS LE CPP !!!
PPU_SpritesLayer.CRASHED = true;
return false;
} else
{
console.log("PPU_SpritesLayer shader programs linked");
}
// shader locations
PPU_SpritesLayer.XY_ATTRIB_LOCATION = gl.getAttribLocation(PPU_SpritesLayer.SHADER_PROGRAM_ID, 'aVertexPosition');
PPU_SpritesLayer.TILESHEET_UV_ATTRIB_LOCATION = gl.getAttribLocation(PPU_SpritesLayer.SHADER_PROGRAM_ID, 'aTilesheetTextureCoord');
PPU_SpritesLayer.SPRITESMAP_UV_ATTRIB_LOCATION = gl.getAttribLocation(PPU_SpritesLayer.SHADER_PROGRAM_ID, 'aSpritesmapTextureCoord');
PPU_SpritesLayer.TILESHEET_TEXTURE_UNIFORM_LOCATION = gl.getUniformLocation(PPU_SpritesLayer.SHADER_PROGRAM_ID, 'uTilesheetSampler');
PPU_SpritesLayer.SPRITESMAP_TEXTURE_UNIFORM_LOCATION = gl.getUniformLocation(PPU_SpritesLayer.SHADER_PROGRAM_ID, 'uTilemapSampler');
PPU_SpritesLayer.PALETTE_TEXTURE_UNIFORM_LOCATION = gl.getUniformLocation(PPU_SpritesLayer.SHADER_PROGRAM_ID, 'uPaletteSampler');
// bool
PPU_SpritesLayer.INITIALIZED = true;
};
PPU_SpritesLayer.ShutDown = function ()
{
if (!PPU_SpritesLayer.CRASHED && PPU_SpritesLayer.INITIALIZED)
{
const gl = PPU_SpritesLayer.CONTEXT3D;
gl.detachShader(PPU_SpritesLayer.SHADER_PROGRAM_ID,PPU_SpritesLayer.VERTEX_SHADER_ID);
gl.detachShader(PPU_SpritesLayer.SHADER_PROGRAM_ID,PPU_SpritesLayer.FRAGMENT_SHADER_ID);
gl.deleteShader(PPU_SpritesLayer.VERTEX_SHADER_ID);
gl.deleteShader(PPU_SpritesLayer.FRAGMENT_SHADER_ID);
console.log("PPU_SpritesLayer shaders deleted");
}
// bool
PPU_SpritesLayer.INITIALIZED = false;
};
// -----------------------------------------------------------------------------
// INSTANCE PROPS
// -----------------------------------------------------------------------------
// instance index
PPU_SpritesLayer.prototype.m_instanceIndex = 0;
// num sprites
PPU_SpritesLayer.prototype.m_numSprites = 0;
// vertex arrays & buffers
PPU_SpritesLayer.prototype.m_sprites_YX = null; //new Float32Array( 8 * this.m_numSprites ); // updated every frame, from uv * matrix
PPU_SpritesLayer.prototype.m_sprites_tilesheet_UV = null; //new Float32Array( 8 * this.m_numSprites ); // updated at init. default 0.0-1.0
PPU_SpritesLayer.prototype.m_spritemap_UV = null; //new Float32Array( 8 * this.m_numSprites ); // theorically updated at init
PPU_SpritesLayer.prototype.m_sprites_indexes = null; //new Uint16Array( 6 * this.m_numSprites );
PPU_SpritesLayer.prototype.m_sprites_XY_buffer = null;
PPU_SpritesLayer.prototype.m_sprites_tileSheet_UV_buffer = null;
PPU_SpritesLayer.prototype.m_spritemap_UV_buffer = null; // all at 0.5 centered on pixels
PPU_SpritesLayer.prototype.m_sprites_indexes_buffer = null;
// arrays & textures for spritemap, palette and scanlines
PPU_SpritesLayer.prototype.m_palette_array = null ; //new Uint8Array( 4 * 16 * 16 );
PPU_SpritesLayer.prototype.m_spritemap_array = null ; //new Uint8Array( 4 * this.m_numSprites );
PPU_SpritesLayer.prototype.m_tileSheet_texture = null; // managed elsewhere
PPU_SpritesLayer.prototype.m_palette_texture = null;
PPU_SpritesLayer.prototype.m_spritemap_texture = null;
// -----------------------------------------------------------------------------
// INSTANCE METHODS
// -----------------------------------------------------------------------------
// build-delete
PPU_SpritesLayer.prototype.build = function( tilesheetTexture, numSprites )
{
// do nothing if not init
if (!PPU_SpritesLayer.INITIALIZED)
{
return null;
}
// instance index
this.m_instanceIndex = PPU_SpritesLayer.NUM_INSTANCES;
PPU_SpritesLayer.NUM_INSTANCES++;
// cache context
const gl = PPU_SpritesLayer.CONTEXT3D;
// args
this.m_numSprites = numSprites;
// alloc CPU arrays and GPU vertex buffers ---------------------------------
// dimension sprites vertex arrays
this.m_sprites_YX = new Float32Array( 8 * this.m_numSprites ); // updated every frame, from uv * matrix
this.m_sprites_tilesheet_UV = new Float32Array( 8 * this.m_numSprites ); // updated at init. default 0.0-1.0
this.m_spritemap_UV = new Float32Array( 8 * this.m_numSprites ); // theorically updated at init, col-row offsets are in spritemap texture
this.m_sprites_indexes = new Uint16Array( 6 * this.m_numSprites );
// cache arrays
var tshUV = this.m_sprites_tilesheet_UV;
var mapUV = this.m_spritemap_UV;
var indxs = this.m_sprites_indexes;
// compute initial values
for ( var iSp = 0; iSp < this.m_numSprites; iSp++ )
{
// uv coords in tileSheet
var it = iSp*8;
// 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0
tshUV[ it + 0 ] = 0.0/16.0 ; tshUV[ it + 1 ] = 1.0/16.0 ;
tshUV[ it + 2 ] = 1.0/16.0 ; tshUV[ it + 3 ] = 1.0/16.0 ;
tshUV[ it + 4 ] = 1.0/16.0 ; tshUV[ it + 5 ] = 0.0/16.0 ;
tshUV[ it + 6 ] = 0.0/16.0 ; tshUV[ it + 7 ] = 0.0/16.0 ;
// uv coords in spriteemap 1-dimension
var im = iSp * 8;
for ( var i=0; i<4; i++ )
{
mapUV[ im + i*2 + 0 ] = ( iSp + 0.5 ) / this.m_numSprites ;
mapUV[ im + i*2 + 1 ] = 0.5 ;
}
// indexes
var ii = iSp * 6;
indxs[ ii + 0 ] = 0 + 4*iSp;
indxs[ ii + 1 ] = 1 + 4*iSp;
indxs[ ii + 2 ] = 2 + 4*iSp;
indxs[ ii + 3 ] = 0 + 4*iSp;
indxs[ ii + 4 ] = 2 + 4*iSp;
indxs[ ii + 5 ] = 3 + 4*iSp;
}
// sprites GPU verts buffers
this.m_sprites_XY_buffer = gl.createBuffer(); // updated at runtime only
this.m_sprites_tileSheet_UV_buffer = gl.createBuffer(); // defaut 0.0 - 1.0
gl.bindBuffer(gl.ARRAY_BUFFER, this.m_sprites_tileSheet_UV_buffer );
gl.bufferData(gl.ARRAY_BUFFER, this.m_sprites_tilesheet_UV, gl.STATIC_DRAW); // will be updated at init later
// for these two ones i could discard array member, we'll see
this.m_spritemap_UV_buffer = gl.createBuffer(); // .5 everywhere, never updated
gl.bindBuffer(gl.ARRAY_BUFFER, this.m_spritemap_UV_buffer );
gl.bufferData(gl.ARRAY_BUFFER, this.m_spritemap_UV, gl.STATIC_DRAW);
this.m_sprites_indexes_buffer = gl.createBuffer(); // never updated
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.m_sprites_indexes_buffer );
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.m_sprites_indexes, gl.STATIC_DRAW); // static buffer, won't be streamed
console.log(" PPU_SpritesLayer instance "+this.m_instanceIndex+" vertices buffers created");
// alloc CPU arrays and GPU textures ---------------------------------------
this.m_tileSheet_texture = tilesheetTexture; // managed elsewhere
this.m_palette_array = new Uint8Array( 4 * 16 * 16 );
this.m_palette_texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.m_palette_texture);
// oldschool rendering
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
// initialize data (may be removed)
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16 , 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.m_palette_array);
this.m_spritemap_array = new Uint8Array( 4 * this.m_numSprites );
this.m_spritemap_texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.m_spritemap_texture);
// oldschool rendering
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
// initialize data (may be removed)
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.m_numSprites, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.m_spritemap_array);
console.log(" PPU_SpritesLayer instance "+this.m_instanceIndex+" textures created");
};
PPU_SpritesLayer.prototype.delete = function()
{
// do nothing if not init
if (!PPU_SpritesLayer.INITIALIZED)
{
console.log('TilesheetTester not initialized');
return null;
}
// cache context
const gl = PPU_SpritesLayer.CONTEXT3D;
// delete arrays and textures ----------------------------------------------
gl.deleteTexture(this.m_palette_texture);
this.m_palette_array = null;
gl.deleteTexture(this.m_spritemap_texture);
this.m_spritemap_array = null;
console.log(" PPU_SpritesLayer instance "+this.m_instanceIndex+" textures deleted");
// delete verts buffers ----------------------------------------------------
gl.deleteBuffer(this.m_sprites_XY_buffer);
this.m_sprites_YX = null;
gl.deleteBuffer(this.m_sprites_tileSheet_UV_buffer);
this.m_sprites_tilesheet_UV = null;
gl.deleteBuffer(this.m_spritemap_UV_buffer);
this.m_spritemap_UV = null;
gl.deleteBuffer(this.m_sprites_indexes_buffer);
this.m_sprites_indexes = null;
console.log(" PPU_SpritesLayer instance "+this.m_instanceIndex+" vertices buffers deleted");
};
// update sprites and palette
PPU_SpritesLayer.prototype.setColor = function ( y, x, r, g, b, a)
{
// voir si ce bordel là est optimisable avec des array 32 (là y'a dla doc webgl à fouiller)
const addr = ( (x&15) | ((y&15)<<4) ) * 4;
let pa = this.m_palette_array;
pa[ addr + 0 ] = r ;
pa[ addr + 1 ] = g ;
pa[ addr + 2 ] = b ;
pa[ addr + 3 ] = a ;
};
PPU_SpritesLayer.prototype.setSprite = function ( index, visible, x, y, indexAscii, paletteY, flipX )
{
x = Math.floor(x); // round coords
y = Math.floor(y);
let xys = this.m_sprites_YX;
const uvs = this.m_sprites_tilesheet_UV;
const iF = index * 8; // index first double
// hide unactive sprite and return
if ( ! visible )
{
for ( let i=0; i<8; i++ )
{
xys[ iF + i ] = -1024 ; // x/y outField
}
return;
}
// compute the pseudo-matrix
const imgW = 128.0, imgH = 128.0; // x y coordinates based on sheet dimensions
const matw = imgW / PPU_SpritesLayer.SCREEN_WIDTH * 2 ;
const math = -imgH / PPU_SpritesLayer.SCREEN_HEIGHT * 2 ;
const matx = x * matw / imgW;
const maty = y * math / imgH;
// tileSheet UV coords are converted to XY coords with "matrix"
for ( let i=0; i<4; i++ )
{
const ix = iF + i*2;
xys[ ix+0 ] = uvs[ ix+0 ] * matw + matx ; // x
xys[ ix+1 ] = uvs[ ix+1 ] * math + maty ; // y
}
// update pixel data in cellList
let colInSheet = indexAscii & 15 ;
if ( flipX )
{
colInSheet = 127 - colInSheet;
}
let rowInSheet = Math.floor( (indexAscii & 255) / 16 );
let colOffset = colInSheet & 15;
let rowOffset = rowInSheet & 15;
let map = this.m_spritemap_array;
const c = index % this.m_numSprites;
map[ 4*c + 0 ] = colOffset << 4 ; // 255->1.0, so 16*16
map[ 4*c + 1 ] = rowOffset << 4 ;
map[ 4*c + 2 ] = paletteY << 4 ;
map[ 4*c + 3 ] = flipX * 255 ; // glsl reads 0.0 / 1.0
};
// drawcall render
PPU_SpritesLayer.prototype.drawCall = function()
{
// cache context
const gl = PPU_SpritesLayer.CONTEXT3D;
// CPU->GPU STREAM PHASE ----------------------------------------------------
// update textures
gl.bindTexture(gl.TEXTURE_2D, this.m_spritemap_texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.m_numSprites, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.m_spritemap_array);
gl.bindTexture(gl.TEXTURE_2D, this.m_palette_texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.m_palette_array);
// update vertices
gl.bindBuffer(gl.ARRAY_BUFFER, this.m_sprites_XY_buffer);
gl.bufferData(gl.ARRAY_BUFFER, this.m_sprites_YX, gl.STATIC_DRAW);
// DRAW PHASE --------------------------------------------------------------
// bind vertex buffers
gl.bindBuffer(gl.ARRAY_BUFFER, this.m_sprites_XY_buffer);
gl.vertexAttribPointer(PPU_SpritesLayer.XY_ATTRIB_LOCATION, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(PPU_SpritesLayer.XY_ATTRIB_LOCATION);
gl.bindBuffer(gl.ARRAY_BUFFER, this.m_sprites_tileSheet_UV_buffer);
gl.vertexAttribPointer(PPU_SpritesLayer.TILESHEET_UV_ATTRIB_LOCATION, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(PPU_SpritesLayer.TILESHEET_UV_ATTRIB_LOCATION);
gl.bindBuffer(gl.ARRAY_BUFFER, this.m_spritemap_UV_buffer);
gl.vertexAttribPointer(PPU_SpritesLayer.SPRITESMAP_UV_ATTRIB_LOCATION, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(PPU_SpritesLayer.SPRITESMAP_UV_ATTRIB_LOCATION);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.m_sprites_indexes_buffer);
// select shader program (revoir si c'est dans le bon ordre)
gl.useProgram(PPU_SpritesLayer.SHADER_PROGRAM_ID);
// bind textures
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this.m_tileSheet_texture);
gl.uniform1i(PPU_SpritesLayer.TILESHEET_TEXTURE_UNIFORM_LOCATION, 0);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, this.m_spritemap_texture);
gl.uniform1i(PPU_SpritesLayer.SPRITESMAP_TEXTURE_UNIFORM_LOCATION, 1);
gl.activeTexture(gl.TEXTURE2);
gl.bindTexture(gl.TEXTURE_2D, this.m_palette_texture);
gl.uniform1i(PPU_SpritesLayer.PALETTE_TEXTURE_UNIFORM_LOCATION, 2);
// draw triangles
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.drawElements(gl.TRIANGLES, 6 * this.m_numSprites, gl.UNSIGNED_SHORT, 0);
gl.disable(gl.BLEND);
};
J'ai fini les benchmark sur la config minimale clodoïd logicom le wave, voilà les résultats:
Maximum 8 tilemaps et 4096 sprites.
Je divise tout par 4 car les clients vont inévitablement faire chier à réclamer un doublage de résolution,
Donc 2 tilemaps et 1024 sprites,
Et vu que dans les jeux web on doit économiser à mort les calculs CPU j'ai divisé les sprites par 2 ça nous fait 512 (256 par calque donc).
Dernier test d'affichage: http://punkcoders.free.fr/glbm/#pipicaca
Maximum 8 tilemaps et 4096 sprites.
Je divise tout par 4 car les clients vont inévitablement faire chier à réclamer un doublage de résolution,
Donc 2 tilemaps et 1024 sprites,
Et vu que dans les jeux web on doit économiser à mort les calculs CPU j'ai divisé les sprites par 2 ça nous fait 512 (256 par calque donc).
Dernier test d'affichage: http://punkcoders.free.fr/glbm/#pipicaca
Osef des jeux on préfère quand du fais du breakdance en vidéo. 😭
Citation de HylienDivin
Osef des jeux on préfère quand du fais du breakdance en vidéo. 😭
J'ai déménagé dans un 29m2 donc t'attendras que j'ai trouvé une salle de danse.
Citation de DisDonc
Ok c'est cool mais c'est où que je clique pour jouer
Pour l'instant y'a pas de jeu, je suis en train de plancher sur le moteur graphique.
Citation de TrapHideux
J'ai déménagé dans un 29m2 donc t'attendras que j'ai trouvé une salle de danse.
J’ai hâte. 🥰
Citation de Blame
Stylax
Tu fait ça avec du Javascript vanilla en parlant direct avec l'api WebGL? Ou bien tu utilise une librairie genre three.js pour faciliter le truc?
J'utilise aucune librairie j'ai tout codé de A à Z.
Par contre pour les versions windows j'utilise la librairie SDL.
Citation de Blame
Stylé
T'a appris ça en utilisant quelle ressources?
Ben j'ai bêtement lu les docs de Mozilla.
Le topic bide sur jvc je vous remercie de l'animer avec des insultes sur mon tee-shirt de village people.
https://www.jeuxvideo.com[...]webgl.htm#post_1224492186
https://www.jeuxvideo.com[...]webgl.htm#post_1224492186
Comme d'habitude avec Froctare, 14 réponses dont 8 de sa part...
Citation de TrapHideux
Le topic bide sur jvc je vous remercie de l'animer avec des insultes sur mon tee-shirt de village people.
c'est toute ta vie qui bide, Froctasse
Bob ta gueule. Jay palu.
bob fais voir ton CV de web-développeur qu'on rigole
Citation de TrapHideux
bob fais voir ton CV de web-développeur qu'on rigole
tiens c'est bizzare il ferme sa gueule
bon putain je dois factoriser une tartine d'algos et là ce soir je suis fatigué et en plus j'ai faim,
je vais peut-être m'y remettre après bouffer on verra si je trouve la force de me doper au tcherno
je vais peut-être m'y remettre après bouffer on verra si je trouve la force de me doper au tcherno
NOUS SOMMES FORTES, NOUS SOMMES FIERES
FEMINISTES RADICALES ET EN COLERE
ok les gonzesses venez bosser dans ma startup je vous paye pareil que les mâles mais je tiens à voir votre force
FEMINISTES RADICALES ET EN COLERE
ok les gonzesses venez bosser dans ma startup je vous paye pareil que les mâles mais je tiens à voir votre force

