diumenge, 29 de maig del 2011

Una de pollosos i gossos

Seré polèmic, que és el que toca.

https://www.asopol.org/2011/05/sobre-la-carga-de-los-mossos-desquadra-en-plaza-cataluna/

http://thelede.blogs.nytimes.com/2011/05/27/police-clash-with-protesters-in-barcelona/?ref=world

Un link és de la policia, i l'altre del NY Times, on veureu uns quans vídeos. Llegiu el primer i mireu (després) els videos, si no els heu vist ja.

Primer de tot una introducció sobre mi per qui no em conegui. Sóc (quasi) enginyer informàtic, i des de l'octubre sóc membre del Partit Pirata Català (Anomenat "Pirates de Catalunya" per que ja existia un "Partit Pirata" espanyol i no ens hi podiem dir sense formar part d'ells rollo PSC). Aquest partit defensa molts dels punts que han anat sortint a les acampades i que n'han estat causa, tot i que no tots. Per fer-vos una idea, un amic meu ha escrit el següent text sobre les demandes dels acampats:

https://docs.google.com/document/d/1nNplofoR06TTPYqJzY69cUHcnJR3lSsEyRms1Z6lQtY/edit?hl=en_US

Hi estic majoritàriament d'acord amb l'Aleix (l'autor dels comentaris) però ràpidament dic que posaria més emfasis a que els diners no plouen del cel i un estat amb "més de tot" és desitjable però difícil, i que toca moltes vegades prioritzar, cosa que els acampats no fan en cap moment, simplement demanen una sobreprotecció total de l'estat, i això en opinió meva acava sent negatiu (és, segons crec jo, un dels grans fracassos dels estats comunistes: la falta d'ambició individual dels seus habitants fa que el sistema no pugui aguantar-se a ell mateix). Tampoc parlaré molt d'aquest tema, que demanaria un post en si mateix.

Estava parlant de Pirates de Catalunya. Una de les coses boniques d'aquest partit és de demana democracia directa (que no participativa) i pretén aconseguir-ho usant les eines que, afortunadament, ens dóna el nostre país, que hem de recordar, les té i afortunadament no és pas cap dictadura (després hi torno). Per veure un exemple de com funciona el partit per dintre, a part de mirar la seva web pirata.cat podeu mirar el link que poso a continuació, que és on es discuteix una desició (també es discuteixen coses per les llistes de correu):

https://xifrat.pirata.cat/ideatorrent/idea/107


Molt bé, hem parlat que jo no estic en contra del que demanen els acampats. Al menys no en contra de tot, i que concretament també penso que el nostre estat democràtic té certes mancances que, sobretot ara la tecnologia i la informació global, ens poden permetre superar via democràcia directa.

Fins hi tot puc entendre que acampin, cosa il·legal, però ara diré el que més llenya em farà caura.

ETA també demana (o demanava) coses "correctes" (la independència d'euskadi, concretament), i feia servir métodes ilícits per aconseguir-ho.

És extremadament obvi que no es pot comparar matar persones amb acampar a una plaça. La diferéncia de gravetat dels dos fets els situa a ordres de magnitud de distància. I tot i així, les dos coses són demanar coses via métodes ilegals. Està clar, doncs, que és un tema d'on podem el llistor, i això no sempre és fàcil Si diem que matar està clarament fora, i ocupar un espai públic està dintre, què hi ha al mig i on marquem la barrera? Sé que em cauràn osties per haver-ho dit, però com a mínim feu-vos la pregunta.

Ara, sobre les càrregues policials. Havent llegit el text de la policia (també tenen dret a defensar-se) queden clar els motius de la càrrega policial: van demanar als indignats que s'apartessin del mig, i ells no ho van fer, i els policies van haver de recórrer a la violència per treure'ls. Assumirem (que és molt assumir) que realment el que venien a fer les brigades de neteja era correcte (seria: endur-se bombones de butà, eines de l'hort i coses perilloses en general; netejar de pixum la plaça, etc... NO seria: endur-se portàtils i apunts de les assamblees, com també van fer). I que, per tant, la feina de la policia era també correcte: garantir que els primers puguin fer la seva feina en condicions i seguretat.

Si assumim el què he dit a dalt (que hi podem discutir, i ja he dit que té matissos), aleshores arribem a un punt: impedir que les brigades de neteja facin la seva feina era (1) incorrecte i (2) buscar-se problemes amb la policia. Arribat a aquest punt era, doncs, feina de la policia, apartar als indignats del mig. Fins aquí, i si s'hagues pogut apartar-los del mig sense violència, crec que estariem tots d'acord. Per tant el problema sembla ser si la policia ha de, o pot, fer servir la violència en aquests casos.

I aqui us vui comentar un punt molt interessant, al meu parer, i és que, en el mateix comentari de l'associació professional de policies (que he enllaçat més amunt) comenta que la violència era el métode "protocolari" de resoldre la situació (gent que ocupa l'espai públic, desobeeix per activa i passiva les ordres d'un agent policial, i que guanya en nombre a aquest), però que caldria buscar una altra manera menys violenta i "espectacular" (en paraules seves) de resoldre-la. I no podria estar més d'acord. Ho remarco per que no vui que ningú oblidi que els agents que eren allà feien la seva feina, malaguanyada aquell dia però que segurament si et roben a la rambla i després t'ajuden els hi donaràs les gràcies, i que no disposaven de mitjans (o coneixements) per resoldre-la d'una altra manera.

És correcte emprar la violència? Segurament no. Mai? Ningú s'ha ficat en una baralla per res? Qui estigui lliure de culpa que tiri la primera pedra.

El que vui resumir aqui, no és si la càrrega policial va ser correcte o incorrecte. Si l'ocupació de plaça catalunya, un espai de tots, és correcte o incorrecte. El que m'agradaria transmetre, és que no tot és blanc o negre, ni és tant fàcil de dir: No, que la policia usi la violència contra gent que ha petat les rodes dels camions de les escombraries, i que no obeeixen per les bones, és dolent.

És molt fàcil dir que la policia va actuar de forma violenta, com animals, i oblidar que dos no es barallen si un no vol, i que si els manifestants haguéssin volgut haguéssin evitat tot l'espectacle. Però clar (i aqui si que em surt la meva vena anti-pollòs) si no estàs a fabor seu, estàs en contra seu.

I aquesta és la trampa que jo, i algún amic meu, hem caigut: expressar públicament que els indignats no tenen la raó absoluta i que, la policia "només" va fer la seva feina. Fent això la gent ens agafa per feixistes, o alguna cosa similar, per molt que pensem que la violència no és la solució i que el problema hagués estat millor resolt d'una altra manera.

Però sabeu què? Fins ara, ningú m'ha dit una altra solució que no sigui "la policia i els camions de la neteja haurien d'haver marxat". Mireu, aquesta solució és igual a "els manifestants haurien d'haver agafat les seves coses, apartar-se, deixar fer la seva feina a BCNeta i després tornar". És un problema de a veure qui cedeix i qui té raó. El que jo vui és que algú em proposi una solució pacífica intermitja.

P.S.: Finalment, sobre el títol del post, és per deixar clar que estic més en contra de les 2 parts que a fabor de cap d'elles. Concretament, crec que els objectius d'ambdós són generalment bons, però els métodes no ho són tant (matissos en tots els casos).

dissabte, 5 de febrer del 2011

Suficiència d'OpenGL ES 2.0 Part II (Framebuffers)

Continuant el post anterior, i una mica en la mateixa línea, avordem un tema "important", sobretot si es tracta de fer efectes abançats: Els Framebuffers.

D'acord, primer de tot, necessitem entendre una mica de teoria sobre on dibuixem les coses i quins espais de memòria ens són disponibles.

Aquests espais de memòria als que em refereixo són els buffers de renderització; allà on guardem informació de color, profunditat, etc... En l'exemple més senzill de OpenGL, disposem de 2 buffers: el front buffer i el back buffer. Aquests buffers guarden informació de color (RGB i a vegades un Alpha que indica "quantitat d'opacitat"), el front buffer es mostra per pantalla mentre que el backbuffer és on dibuixem. Un cop acavem de dibuixar un frame, intercanviem el front i el back, així no es veu mai "mentre dibuixem" sinó que veiem sempre dibuixos sencers.

Addicionalment se li poden afegir 2 buffers: el depth buffer i el stencil buffer. Sobre l'stencil no en parlarè gaire, per no dir gens; mai l'he fet servir i no sé ben bé per a què serveix, però el depth buffer és molt útil. Aquest búffer de profunditat (depth) guarda la profunditat on se suposa que cada pixel està pintat. Això ens permet un mètode senzill per renderitzar les coses que estàn més a prop: si anem a dibuixar una cosa més llunyana que la que hi ha dibuixada, no la dibuixem. Si és més propera, la dibuixem i actualitzem el depth.

Molt bé, ara veiem que per renderitzar necessitem un buffer de color i, opcionalment, un de profunditat i/o un de stencil. Per defecte normalment en tenim un de cada (més el front buffer), però a vegades ens interessa dibuixar coses "fora de la pantalla". Per exemple: Imaginem-nos que estem en un joc, en una sala amb càmeres de videovigilància. Aquestes càmeres mostren, en temps real, altres habitacions. Per a acomplir aquest efecte, podem renderitzar aquestes altres habitacions en una textura cada una i, posteriorment, renderitzar la textura a la càmera.

Això és el que es coneix com a off-screen rendering, i consisteix en crear un "Framebuffer object", que és una col·lecció de buffers de distínta índole, i dir-li a l'openGL que renderitzi sobre aquest. Els buffer poden ser de 2 maneres: o bé una textura, o bé un Renderbuffer. La diferència essencial és que no tenim fàcilment accessible la informació dels Renderbuffers, mentre que una textura la tenim sempre a mà.

Codi:

//------------------------------------------------------------

//Primer creem els Renderbuffers, que poden servir com a color,
//profunditat o stencil
GLuint renderbuffers[2];
glGenRenderbuffers(2, &(renderbuffers[0]));

//activem el renderbuffer
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[0]);

//definim com és el renderbuffer
glRenderbufferStorage(GL_RENDERBUFFER,
                      format,         //Format intern
                      width, height); //dimensions

// Formats estàndard:
// GL_RGB565, GL_RGBA4, GL_RGB5_A1,         -- Color
// GL_DEPTH_COMPONENT16, GL_STENCIL_INDEX8
//
// Formats amb l'extensió GL_OES_rgb8_rgba8
// GL_RGB8_OES, GL_RGBA8_OES
//
// Formats amb l'extensió GL_OES_depth24 / GL_OES_depth32
// GL_DEPTH_COMPONENT24_OES, GL_DEPTH_COMPONENT32_OES
//
// Formats amb l'extensió GL_OES_stencil1 / GL_OES_stencil4
// GL_STENCIL_INDEX1, GL_STENCIL_INDEX4
//
// Formats amb l'extensió GL_OES_packed_depth_stencil
// GL_DEPTH24_STENCIL8_OES

// Les dimensions cal que siguin iguals o menors a
// GL_MAX_RENDERBUFFER_SIZE
 
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[0]);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 800, 600);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[1]);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 800, 600);



//Crear identificadors de frambuffer,
// de forma similar a les textures:
GLuint framebufferID;
glGenFramebuffers(1,                //nombre d'id a generar
                  &framebufferID);

// Activar el framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);

// Aquesta funció ens serveix tant per especificar les propietats
//del framebuffer (punts d'anclatge) com per indicar que volem
//que es renderitzi a aquest. Per tornar a renderitzar als buffer
//"normals" hem de fer:
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// Lligar un renderbuffer al framebuffer
gl_FramebufferRenderbuffer(GL_FRAMEBUFFER,
                           punt_d_anclatge,
                           GL_RENDERBUFFER,
                           renderbufferID); //0 per no anclar-hi res

// Punts d'anclatge:
// GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT
// Com a nota important, saber que en OpenGL estàndard hi ha més
//punts d'anclatge, concretament, els de color 1, 2, 3... Això 
//serveix per poder pintar a més d'un lloc a la vegada, i ho 
//explicarè als fragment shaders.

//Continuant amb l'exemple
gl_FramebufferRenderbuffer(GL_FRAMEBUFFER,
                           GL_COLOR_ATTACHMENT0,
                           GL_RENDERBUFFER,
                           renderbuffers[0]);
gl_FramebufferRenderbuffer(GL_FRAMEBUFFER,
                           GL_DEPTH_ATTACHMENT,
                           GL_RENDERBUFFER,
                           renderbuffers[1]);
gl_FramebufferRenderbuffer(GL_FRAMEBUFFER,
                           GL_STENCIL_ATTACHMENT,
                           GL_RENDERBUFFER,
                           0);

//Comprovar errors
GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);

//Result pot ser:
// GL_FRAMEBUFFER_COMPLETE -- OK
// GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT -- Algun error
//                                      -- en algun anclatge.
// GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT -- No hi ha cap
//                                              --anclatge
// GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS -- Anclatges amb
//                                      -- dimensions diferents
// GL_FRAMEBUFFER_INCOMPLETE_FORMATS -- Algun format no suportat
// GL_FRAMEBUFFER_UNSUPPORTED -- Combinació d'anclatges i formats
//                            -- no suportats.


// Com s'ha dit anteriorment, la gràcia de tot plegat és la de
//dibuixar a una textura, per això anclem una textura al 
//framebuffer com ho anclavem un renderbuffer
glFramebufferTexture2D(GL_FRAMEBUFFER,
                       punt_d_anclatge, //Només color o profunditat
                       target,
                       texture_id,
                       0); //nivell mipmap.

// Targets:
// GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP_POSITIVE_X, ...

//EXTRA: Textures 3D
glFramebufferTexture3DOES(GL_FRAMEBUFFER,
                          GL_COLOR_ATTACHMENT0, //No depth
                          GL_TEXTURE_3D_OES,
                          texture_id,
                          0, //nivell mipmap.
                          z_offset); //profunditat

// Finalment i nogensmenys important:
glDeleteRenderbuffers(2, &(renderbuffers[0])); //La pots liar si 
                           //encara està en ús en un framebuffer
glDeleteFramebuffers(1, &framebufferID);

//------------------------------------------------------------


Per altra banda, i de manera molt ràpida, m'agradaria introduir una altra funcionalitat molt similar, encara que amb un rendiment més baix (tot i que a vegades necessitem fer-la servir en front de framebuffers). Aquesta és simplement copiar el contingut de l'actual framebuffer (el back buffer en cas de no tenir un framebuffer activat) a una textura.


//------------------------------------------------------------
glCopyTexImage2D(target, // GL_TEXTURE_2D, GL_TEXTURE_CUBE...
                 0,      // nivell mipmap
                 texture_format,
                 x, y,   // On de la pantalla comencem a copiar
                 w, h,   // tamany de la textura / àrea a copiar
                 0);     // border

// El format pot ser
// GL_RGBA, GL_RGB, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA
// A més, en OpenGL estàndard (MAI en ES) es pot copiar el depth
// buffer si s'especifica el format
// GL_DEPTH_COMPONENT


// Per copiar a una subregió d'una textura
glCopyTexSubImage2D(target, 0, texture_format,
                    xoffset, // coordenades on començar a copiar
                    yoffset, // a la textura
                    x, y, w, h, 0);

// Les 3D només poden fer servir la "SubImage"
glCopyTexSubImage3DOES(target, 0, texture_format,
                       xoffset, yoffset,
                       zoffset, // coordenada z a on es copia
                       x, y, w, h, 0);
//------------------------------------------------------------

 I fins aqui tots els temes relacionats amb renderitzar múltiples vegades un frame. Amb això es poden aconseguir efectes xulos, ja sigui:
Glow, Blur, HDR, Ombres (Shadowmap)...

divendres, 28 de gener del 2011

Guia ràpida d'OpenGL (ES)

Molts bons el que sigui.

He estat llegint un llibre d'OpenGL ES 2.0, la versió per sistemes integrats d'OpenGL. La gràcia (explicat ràpidament) de la versió ES és que és essencialment el mateix que la versió "mare" però simplificada, o sigui, amb totes les funcions "redundants" eliminades. Un programa fet doncs, en OpenGL ES és pràcticament un 100% portable a OpenGL normal (excepte que les extensions són diferens, petits detallets).

Què vui fer jo ara? Escriure'm un resumet del llibre, ja que l'he de tornar a la biblioteca eventualment.

Així que, què, saveu com va OpenGL, més o menys? El de veritat, el dels Shaders, eh!

Essencialment, el que un ha de fer perque es dibuixi alguna cosa és especificar un seguit de geometria (Triangles, línees o "punts"), que recorre un seguit de transformacions fins que són pintades. Quines transformacions?

Pipeline:
  1. Vertex Shader: Agafa paràmetres que li dónes directament i les passes a la següent fase. El paràmetre important a passar són les coordenades de "clip" (coordenades de retallada), que essencialment són les coordenades dels vertexos normalitzades.
  2. Rasterització: Es divideix en diferents fases, l'objectiu és trobar els fragments que faràn el "Fragment Shader.
    1. Divisió de perspectiva: S'agafen les coordenades de clip (xc, yc, zc, wc) i es transformen a coordenades de Device (xd, yd, zd) = (xc/wc, yc/wc, zc/wc). Aquelles coordenades fóra del rang [-1, 1] són descartades.
    2. Transformació de Viewport: Transforma les anteriors coordenades a coordenades de pantalla (les x i y) i també transforma proporcionalment les z a un rang que tu mateix has especificat.
    3. Rasterització: Un cop tens cada vèrtex situat en un pixel, "s'envien" tots els pixels intermitjos al Fragment Shader. Prèviament es fa el culling (Eliminar els triangles que estiguin mirant en contra la càmera.
  3. Fragment Shader: Agafa paràmetres interpolats del Vertex Shader i els utilitza per definir el color del fragment. A més disposa de les coordenades del fragment en pantalla, les coordenades dels point-sprites, i si la cara mira o no a càmera.
  4. Operacions per fragment: També n'hi ha vàries.
    1. Scissor Testing: Fa que només es pintin pixels definits en un rectangle definit.
    2. Stencil Test: No ho he entès mai, ni mai he vist cap exemple de ningú fent-ho servir.
    3. Depth Test: Decideix si un fragment es dibuixa o no segons la seva profunditat.
    4. Blending: Barreja el color amb el color anterior.
    5. Dithering: Tampoc ho he fet servir mai.
Coses Ràpides que cal saber de shaders:

Els Shaders tenen 3 tipus de "variables globals":
  • Uniform: Són paràmetres que comparteix tota la geometria, on la geometria és allò que dibuixes d'un cop, un model, vamos. Exemples serien les matrius de transformació, les llums, etc...
  • Attribute: Són paràmetres per vèrtex. Per exemple Coordenades-Objecte, Normals, coordenades de textura i altres.
  • Varying: Aquestes s'escriuen al Vertex Shader i es llegeixen al Fragment Shader. És la manera de passar informació de l'una a l'altre.
Cada shader es defineix amb una funció "main" de tota la vida.

Com es creen els shaders? "Fàcil"!

Primer cal crear ambdós shaders:


//---------------------------------------------------------
GLenum type; //GL_VERTEX_SHADER | GL_FRAGMENT_SHADER

GLuint shader_object = glCreateShader(type);

glShaderSource( shader_object, 
                count,   // número d'strings que passes
                strings, // array de char*, amb el codi
                lenghts);// array de int, amb la llargada de cada
                         // string. Si és NULL se suposa que
                         // acaven en '\0'. Si un element és
                         // negatiu se suposa que aquell acava
                         // en '\0'.

glCompileShader( shader_object );
glGetShaderiv( shader_object,
               param,    // GL_COMPILE_STATUS
                         // GL_DELETE_STATUS
                         // GL_INFO_LOG_LENGTH
                         // GL_SHADER_SOURCE_STATUS
                         // GL_SHADER_TYPE
               &result);

//Comprovar que el compile status sigui true, sino agafar el log
if(!result) {
  int len;
  glGetShaderiv( shader_object, GL_INFO_LOG_LENGTH, len);

  char* infoLog = new char[len];
  glGetShaderInfoLog(shader_object,
                     len,
                     NULL, //llargada, com que ja la savem, null
                     infoLog);

  printf("Log: %s", infoLog);
}

//Eventualment
glDeleteShader(shader_object);
//---------------------------------------------------------

Un cop creats els shaders (Vertex i Fragment), cal lligar-los:

//---------------------------------------------------------
GLuint vertex_shader, fragment_shader;

GLuint shader_program = glCreateProgram();

glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);

//glDetachShader( ... )
glLinkProgram(shader_program); //Fer el link de les "coses"

//glValidateProgram(shader_program) serveix per validar i agafar
//info per el log, però és lent i només s'ha d'usar per "debugar"
//i buscar errors.

glProgramiv( ... ); 
//similar al de shader objects, amb paràmetres
//GL_ACTIVE_ATTRIBUTES             --nombre d'atributs
//GL_ACTIVE_ATTRIBUTES_MAX_LENGTH  --len de l'atribut més llarg

//GL_ACTIVE_UNIFORMS               -- "
//GL_ACTIVE_UNIFORMS_MAX_LENGTH    -- "
//GL_ATTACHED_SHADERS              -- nombre de shaders afegits
//GL_DELETE_STATUS                 -- si es vol eliminar
//GL_INFO_LOG_LENGHT               --
//GL_LINK_STATUS                   -- si s'ha linkad bé
//GL_VALIDATE_STATUS               -- si ha validat

glGetProgramInfoLog( ... ); // com el dels objectes.

//Eventualment
glDeleteProgram( shader_program );
//---------------------------------------------------------

Un cop tenim els shaders compilats i tot, cal agafar les localitzacions dels "uniforms". Amb les localitzacions serem capaços d'escriure aquests valors. "Passar-los" al shader.

Hi ha una funció, glGetActiveUniform, que serveix per saber quina "uniform" hi ha en cada posició i quin tipus té, però aquesta no és la manera normal de buscar-ho (ja sabem quines "uniform" hi ha en el shader, l'hem escrit nosaltres!).

GLint uniformLocation = glGetUniformLocation( shader_program, "nom_uniform");

Així tenim la localització, que podem fer servir així:

void glUniform1f(GLint location, GLfloat v0);

Coses a tenir en compte: Per fer-ho servir el shader ha d'estar "actiu" (més, després) i tmb que n'hi ha moltes, de funcions, i es troben a [1].

Els atributs s'agafen de manera similar.

GLint attributeLocation = glGetAttributeLocation( shader_program, "nom_attribute");

Com preparar la "Geometria"

No m'estaré de métodes arcaics per definir geometria i aniré directament al métode més "eficient".

Conceptualment es tracta de pujar a memória VRAM, memòria de la targeta gràfica, totes les dades necessàries per dibuixar la geometria, i posteriorment cridar-la quan calgui. L'algoritme vé a ser el següent:
  1. En una fase de "init", definir i omplir els buffers.
  2. En una fase de "render":
    1. Activar el Shader que s'utilitza ( glUseProgram(program_id); ).
    2. Definir totes les Uniforms que fa servir el Shader
    3. Fer la crida de "Pinta la geometria".
  3. En una fase de "cleanup" eliminar els buffers.
Què són i com funcionen els buffers? Imaginem-nos que volem renderitzar el següent cuadrat:

[0] ----- [1]
 |         |
 |         |
 |         |
[2] ----- [3]

Aquest té 4 vertexos, amb coordenades [0 => (0, 5, 0)], [1 => (5, 5, 0)], [2 => (0, 0, 0)], [3 => (5, 0, 0)], i amb coordenades de textura [0 => (0, 1)], [1 => (1, 1)], [2 => (0, 0)], [3 => (1, 0)]. Podríem fer un array de la següent manera:

float vertex_data[] = {0, 5, 0, 0, 1, //primer vertex
                       5, 5, 0, 1, 1,
                       0, 0, 0, 0, 0,
                       5, 0, 0, 1, 0  //últim vertex
                      };

Per indicar com s'ha de dibuixar, es pot fer indexat. Primer de tot, cal dividir la geometria en triangles, podem fer 2 triangles en aquest cas: el {0, 2, 1} i el {1, 2, 3}. Així li podem indicar a OpenGL que dibuixi la geometria {0, 2, 1, 1, 2, 3}.

uint16 index_data[] = {0, 2, 1, 1, 2, 3};

Abdós buffers es poden guardar a VRAM i posteriorment activar i utilitzar.

Creant Buffers

Aqui expliquem com crear els buffers, o sigui, la part de "init"


//----------------------------------------------------------
GLuint bufferIds[2];

glGenBufferData(2, bufferIds); //Generem 2 buffers

glBindBuffer(GL_ARRAY_BUFFER, bufferIds[0]); //activem el buffer
                                             //com a buffer de
                                             //dades
glBufferData(GL_ARRAY_BUFFER,   
             numVert * sizeVert, //Tamany que tindran les dades
             vertex_data,        //Dades
             GL_STATIC_DRAW);    //Mode. Li dóna pistes a la gràfica
             //GL_STATIC_DRAW  -- escrit 1, usat molt
             //GL_DYNAMIC_DRAW -- escrit molt, usat molt
             //GL_STREAM_DRAW  -- escrit 1, usat poc

           //GL_ELEMENT... serveix per indexos
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferIds[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, index_data, GL_STATIC_DRAW);

//----------------------------------------------------------
Com a nota adicional, sempre es pot re-crear les dades amb "glBufferData" o canviar una part amb "glBufferSubData" (tot i que si l'has creat amb "STATIC_DRAW" puteges al driver).

Emprant Buffers

Aqui expliquem com renderitzar usant buffers, o sigui la crida a "pintar geometria".


//-------------------------------------------------------------

  //Activem el buffer de vertexos que farem servir
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId);

  //Activem el buffer d'indexos que farem servir
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexBufferId);


  //activem els atributs del shader
glEnableVertexAttribArray(position_attrib); 
glEnableVertexAttribArray(texcoord_attrib); 

glVertexAttribPointer(position_attrib,  // atribut que usem
                      3,         //nº de dades a l'atribut
                      GL_FLOAT,  //tipus de dades
                      GL_FALSE,  //normalització
                      vtxStride, //distancia entre un vtx
                                 //  i el següent
                      0);        //distancia entre l'inici del
                                 //  vtx i les dades en qüestió.     

     /**********************************************************\
     *   Sobre la normalització, serveix per quan usem un tipus *
     * de dades diferent a float i volem que al passar-les a    *
     * float OpenGL les transformi al rang [-1, 1] o no.        *
     \**********************************************************/

     /**********************************************************\
     *   Sobre els tipus de dades, poden ser GL_BYTE,           *
     * GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, *
     * GL_FLOAT, GL_HALF_FLOAT_OES/GL_HALF_FLOAT_ARB            *
     \**********************************************************/

glVertexAttribPointer(texcoord_attrib,

                      2,        
                      GL_FLOAT, 

                      GL_FALSE, 

                      vtxStride,
                      sizeof(float)*3);

glDrawElements(GL_TRIANGLES,      //Tipus de primitiva
               6,                 //nº de indexos
               GL_UNSIGNED_SHORT, //tipus de dades
               0);                //distància entre l'inici del 
                                  //  buffer i el primer index. 

// Tipus de primitives:
//GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP,
//GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN

// Tipus de dades als indexos
//GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT
//La darrera necessita de l'extensió OES_element_index_uint
       
glDisableVertexAttribArray(position_attrib); 
glDisableVertexAttribArray(texcoord_attrib); 
//-------------------------------------------------------------

Textures:

Les textures en OpenGL sempre han estat un petit percal. No m'extendré massa, però coses "importants":


//----------------------------------------------
glGenTextures(num, &id); //genera textures
glDeleteTextures(num, &id); //ejem

  //Activar textura
glBindTexture(tipus, //GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP
              id);

  //Definir la informació
glTexImage(capa,
           nivell,         //Nivell de mipmap. Deixeu-lo a 0
           internalFormat, //format intern
           width,         
           height,
           border,         //en OpenGL ES, 0.
           externalFormat, //cal que sigui el mateix que l'intern.
           dataType,       //tipus de dades
           data);          //dades, per "files"

// Capa:
// Per textures 2D, GL_TEXTURE_2D
// Per Cubemap s'han de definir totes 6 cares:
// GL_TEXTURE_CUBE_MAP_POSITIVE_X, ...NEGATIVE_X, ...

// Formats:
//GL_RGBA, GL_RGB, GL_LUMINANCE_ALPHA, GL_LUMINANCE, GL_ALPHA
//Pensar en la luminance com a "escala de grisos"

// Tipus de dades:
//GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_4_4_4_4,
//GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_5_6_5

  //Definir com es filtra la imatge quan es fa més gran.
glTexParameteri( tipus,
                 GL_TEXTURE_MAG_FILTER,
                 param); //GL_NEAREST / GL_LINEAR

  //Definir com es filtra la imatge quan es fa més petita.
glTexParameteri( tipus,
                 GL_TEXTURE_MIN_FILTER,
                 param); 
              //GL_NEAREST, GL_LINEAR
              //GL_NEAREST_MIPMAP_NEAREST x4 combinacions
//Definir què fa una textura quan té una coordenada fora de [0,1]
glTexParameteri( tipus,
                 GL_TEXTURE_WRAP_S, //O t
                 GL_REPEAT); //GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT



glGenerateMipmap(tipus); //Genera automàticament un mipmap per la 
                         //textura activa

//Finalment parlem de com agafar una textura des del shader.
//Per tal de fer-ho, necessitem una "uniform" especial, anomenada
//"sampler" ("sampler2D" o "samplerCube")

//Activem la textura en un la unitat 0:
glActiveTexture(GL_TEXTURE0); //GL_TEXTURE1, ...
glBindTexture(tipus, textureId);

//Fem que el sampler apunti a la unitat 0
glUniform1i(sampler_uniform, 0);

//----------------------------------------------
També hi ha un altre tipus de textura, la textura3D, que és estandard a OpenGL i a OpenGL ES necessita de l'extenció "GL_OES_texture_3D". Funciona pràcticament igual amb una funció extra per carregar-la "glTexImage3D"[OES] amb un paràmetre adicional indicant la profunditat.

Adicionalment podem crear textures de "profunditat" si l'extenció "GL_OES_depth_texture" està disponible. Això serveix essencialment amb el tema dels pBuffers (vist més endavant) i es creen amb un format "GL_DEPTH_COMPONENT" i tipus "GL_UNSIGNED_SHORT" o "GL_UNSIGNED_INT" si estàn disponibles.


Continuaré en un altre moment. Falta per fer:

  • pBuffers
  • Vertex Shaders
  • Fragment Shaders
  • Operacions post-shader
  • Exemples

[1] http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml

dimarts, 30 de novembre del 2010

Manifest per una xarxa neutral

Els ciutadans i les empreses usuàries d'Internet adherides a aquest text manifestem:
  1. Que internet és una Xarxa neutral per disseny, des de la seva creació a la seva actual implementació, en la que la informació flueix de forma lliure, sense discriminació segons origen, destí, protocol o contingut.
  2. Que les empreses, emprenadors i usuaris d'Internet han pogut crear serveis i productes en aquesta Xarxa Neutral sense necessitat d'autoritzacions ni acords previs, donant pas a una barrera d'entrada pràcticament innexistent que ha permès una explosió creativa, d'innovació i de serveis que defineis l'estat de la xarxa actual.
  3. Que tots els usuaris, emprenadors i empreses d'Internet han pogut definir i oferir els seus seveis en condicions d'igualtat duent el concepte de lliure competència fins extrems mai vistos abans.
  4. Que Internet es el vehicle de lliure expresió, lliure informació i desenvolupament social més important amb el que comptem ciutadans i empreses. La seva natura no pot ser posada en perill sota cap concepte.
  5. Que per possibilitar aquesta Xarxa Neutral les operadores han de transportar els paquets de dades de forma neutral sense actuar com a "aduaners" del tràfic i sense afavorir o perjudicar a uns continguts en front d'altres.
  6. Que la gestió del tràfic en situacions puntuals i exceptionals de saturació de les xarxes ha de transcórrer de forma transparent, d'acord amb criteris homogénis i d'interés públic i no discriminatoris ni comercials.
  7. Que aquesta restricció excepcional del tràfic per part de les operadores no pot convertir-se en una alternativa sostinguda a la inversió en xarxes.
  8. Que aquesta Xarxa Neutral es veu amenaçada per operadores interessades a arribar a acords comercials per els que es privilegii o degradi el contingut segons la seva relació comercial amb dita operadora.
  9. Que algunes operadores del mercat volen "redefinir" la Xarxa Neutral per a emprar-la d'acord amb els seus interessos, i aquesta pretenció cal que sigui evitada; la definició de les regles fonamentals d'Internet han de basar-se en l'interès d'aquells que l'utilitzen, no d'aquells que el proveeixen.
  10. Que la resposta en front d'aquesta amenaça per la xarxa no pot ser la inacció: no fer res equival a permetre que interesos privats puguin de facto emprar pràctiquesque afectin les llibertats funamentals dels ciutadans i la capacitat de les empreses per competir en igualtat de condicions.
  11. Que és necessari i urgent instar al Gobern a protegir de manera clara i inequívoca la Xarxa Neutral, amb la fí de protegir el valor d'Internet de cara al desenvolupament d'una economia més productiva, moderna, eficient i lliure d'injerències i intromisions indegudes. Per això és necessari que qualsevol moció que s'aprovi vinculi de manera indissoluble la definició de Xarxa Neutral en el contingut de la futura llei que la promogui, i no condicioni la seva aplicació a cuestions que poc tinguin a veure amb aquesta.






A continuació us adjunto l'original en Castellà:


Los ciudadanos y las empresas usuarias de Internet adheridas a este texto manifestamos:
1.- Que Internet es una Red Neutral por diseño, desde su creación hasta su actual implementación, en la que la información fluye de manera libre, sin discriminación alguna en función de origen, destino, protocolo o contenido.
2.- Que las empresas, emprendedores y usuarios de Internet han podido crear servicios y productos en esa Red Neutral sin necesidad de autorizaciones ni acuerdos previos, dando lugar a una barrera de entrada prácticamente inexistente que ha permitido la explosión creativa, de innovación y de servicios que define el estado de la red actual.
3.- Que todos los usuarios, emprendedores y empresas de Internet han podido definir y ofrecer sus servicios en condiciones de igualdad llevando el concepto de la libre competencia hasta extremos nunca antes conocidos.
4.- Que Internet es el vehículo de libre expresión, libre información y desarrollo social más importante con el que cuentan ciudadanos y empresas. Su naturaleza no debe ser puesta en riesgo bajo ningún concepto.
5.- Que para posibilitar esa Red Neutral las operadoras deben transportar paquetes de datos de manera neutral sin erigirse en “aduaneros” del tráfico y sin favorecer o perjudicar a unos contenidos por encima de otros.
6.- Que la gestión del tráfico en situaciones puntuales y excepcionales de saturación de las redes debe acometerse de forma transparente, de acuerdo a criterios homogéneos de interés público y no discriminatorios ni comerciales.
7.- Que dicha restricción excepcional del tráfico por parte de las operadoras no puede convertirse en una alternativa sostenida a la inversión en redes.
8.- Que dicha Red Neutral se ve amenazada por operadoras interesadas en llegar a acuerdos comerciales por los que se privilegie o degrade el contenido según su relación comercial con la operadora.
9.- Que algunos operadores del mercado quieren “redefinir” la Red Neutral para manejarla de acuerdo con sus intereses, y esa pretensión debe ser evitada; la definición de las reglas fundamentales del funcionamiento de Internet debe basarse en el interés de quienes la usan, no de quienes la proveen.
10.- Que la respuesta ante esta amenaza para la red no puede ser la inacción: no hacer nada equivale a permitir que intereses privados puedan de facto llevar a cabo prácticas que afectan a las libertades fundamentales de los ciudadanos y la capacidad de las empresas para competir en igualdad de condiciones.
11.- Que es preciso y urgente instar al Gobierno a proteger de manera clara e inequívoca la Red Neutral, con el fin de proteger el valor de Internet de cara al desarrollo de una economía más productiva, moderna, eficiente y libre de injerencias e intromisiones indebidas. Para ello es preciso que cualquier moción que se apruebe vincule de manera indisoluble la definición de Red Neutral en el contenido de la futura ley que se promueve, y no condicione su aplicación a cuestiones que poco tienen que ver con ésta.
La Red Neutral es un concepto claro y definido en el ámbito académico, donde no suscita debate:los ciudadanos y las empresas tienen derecho a que el tráfico de datos recibido o generado no sea manipulado, tergiversado, impedido, desviado, priorizado o retrasado en función del tipo de contenido, del protocolo o aplicación utilizado, del origen o destino de la comunicación ni de cualquier otra consideración ajena a la de su propia voluntad. Ese tráfico se tratará como una comunicación privada y exclusivamente bajo mandato judicial podrá ser espiado, trazado, archivado o analizado en su contenido, como correspondencia privada que es en realidad.
Europa, y España en particular, se encuentran en medio de una crisis económica tan importante que obligará al cambio radical de su modelo productivo, y a un mejor aprovechamiento de la creatividad de sus ciudadanos. La Red Neutral es crucial a la hora de preservar un ecosistema que favorezca la competencia e innovación para la creación de los innumerables productos y servicios que quedan por inventar y descubrir. La capacidad de trabajar en red, de manera colaborativa, y en mercados conectados, afectará a todos los sectores y todas las empresas de nuestro país, lo que convierte a Internet en un factor clave actual y futuro en nuestro desarrollo económico y social, determinando en gran medida el nivel de competitividad del país. De ahí nuestra profunda preocupación por la preservación de la Red Neutral. Por eso instamos con urgencia al Gobierno español a ser proactivo en el contexto europeo y a legislar de manera clara e inequívoca en ese sentido.

divendres, 5 de novembre del 2010

Noticietes

M'ha arribat la notícia que fa prop de més i mig que no escric res a aquest blog.

Raons? Baja, ningú s'ha queixat, he començat la uni, he començat a fer coses diverses que duen força feina...

Anirem a pams: He entrat al master de videojocs de la UAB. Puc dir-ne què en penso? De moment, quan només he fet 4 setmanes (3 de "teoria" i 3 dies de pràctica, aquesta ha estat una setmana curta) m'ha agradat força el que he vist, i el que intueixo per al futur: apendre a treballar en grup. Ara en sério. Aqui serem, si no falla res, uns 5 programadors i un parell d'artistes (que ja veurem com va lo dels artistes, ja que hi ha "problemilles"...), i també hi ha moltíssima feina, així que ningú se salvarà de pringar.

Per posar un exemple, hem tardat 3 dies en configurar el VS, i encara no estem del tot d'acord. Amb prou feines hem acabat la feina que se suposava que hauriem de fer aquesta setmana!!!

L'objectiu final del màster serà crear una demo tecnològica entre "tots". Hem plantejat un parell de propostes:
  • Joc shooter en un futurista "retro" (amb elements desfassats, fora de temps, per mostrar declivi)
  • Un plataformes estúpid de ninjas vs pirates amb ambientacions históriques caricaturesques. Concretament aqui seràs un ninja a l'anic egipte on estàn construint un esfinx del capità pirata.
Farem la primera opció, no us enganyeu, però ens ho hem passat d'allò més bé escrivint tonteries per la segona xD


Altres coses a fer? No podia faltar la nota política. Després del desencant dels partits independentistes (reagrupament, SCI...) vaig passarma a pirata.cat, com els que van llegir l'última entrada van deduir. Avui estava pensant en coses de copyright i volia escriure una entrada al respecte, però he decidit fer una petita re-presentació de mi mateix després de tant de temps sense escriure.

Què em toca fer a pirata.cat? Practicament res, a vegades els ajudo una mica, l'altre dia vaig estar unes hores muntant les llistes electorals amb ells. Sembla mentida, però ens presentem a les 4 diputacions (cosa no fàcil) i amb més dones de l'estrictament necessàri (40% mínim de cada sexe, i cada grup de 5 cal que sigui 2/3 o 3/2, nosaltres crec que arrivem al 45% o 46% de dones a barcelona, on s'han de presentar 80 persones!). Recordem que pirata.es no es va poder presentar ja que no complia el requisit de la paritat (pobrets...).

Recompensa? Sóc 18è a la llista de barna. Com de dalt és això? A ERC haguès entrat al 2006 (en van treure 21), però no al PP ni a ICV (C's no hauria d'existir, com tothom sap). Fent regles de 3 extranyes, necessitaria que pirata.cat atregués 266.000 vots a la província de Barcelona, una fita difícil.

Arribarà pirata.cat al 3% de vots necessàri per entrar al parlament? Tot és una fita, i si arriba poques coses "pràctiques" podrem fer, PERÒ, tindrem veu, i tenir veu, encara que el vot que tinguis sigui minso, és important, com ja s'ha vist al parlament europeu (van firmar en contra d'ACTA a iniciativa del partit pirata suec, que hi té 2 representants. Què és ACTA? Una llarga história, certament...[1]) i moltes coses que pirata.cat defensa són fàcilment defensables des de altres partits, l'objectiu no és tant governar (des del meu punt de vista) com posar certes coses a l'agenda política, diguise'n democràcia directa, una racionalització del copyright (més en un post que farè més tard), una descriminalització del ciutadà (Canon, etc...), neutralitat de la xarxa, bla bla bla...

Una altra cosa semi-important que vui dir: hi van haver bufetades per no anar de cap de llista, pràcticament. Dels 3 candidats que hi van haver destaco el que finalment anirà 6è a les llistes, un profesor de català nascut a valència que fa temps que ajuda a la comunitat del software lliure català (i valencià i balear, per extenció). El perfil del candidat final ja el sabreu si mireu al blog de pirata.cat, i de l'últim teníem un poeta, així que no tothom és un informàtic (o biotecnòleg, estan molt amoïnats per el tema de les patents d'ADN. Sona xungo? Ho és!!!).

[1] http://es.wikipedia.org/wiki/Anti-Counterfeiting_Trade_Agreement

P.S.: M'he equivocat al posar els resultats del 2006, ERC va treure 11 diputats, així que ni a ERC entraria xDDDDD. Per treure'n 18 es necessiten uns 450.000 (però depèn tot, obviament, del % de participació)

dimarts, 14 de setembre del 2010

Pirata.cat

Aquestes eleccions, 29-N, seràn unes de les més disputades últimament,  sobretot, pel que fa a partits nous (després veurem els anàlisis a posteriori, quan res hagi canviat).

Tenim, així interessantment, Reagrupament, Solidaritat Catalana per la  Independència i, menys nou, Ciutadans. Parlo de ciutadans, que ja té una legislatura de vida, per posar el mateix exemple, però a l'altra banda,  o sigui, un partit nou "anti-catalanista", quan els primers són els  partits nous "catalanistes".

Per què apareixen aquests partits? Una raó important, al meu parer és la  "decepció" als partits tradicionals. Decepció per que no aporten  solucions prou "granulars", en altres paraules, quan toca votar, toca  votar un paquet monolític de projecte, sense espai a modificacions. Ens  estàn dient que només hi ha 6 (CiU, PSC, ERC, ICV, PP, C's) maneres  diferents d'encarar els próxims 4 anys? I els punts mitjos, i les  combinacions? Potser vui un model d'autogovern com el que proposa ERC, però unes polítiques socials de ICV.

A tot això han aparegut els nous partits. C's s'explica per  l'alternativa centralitzadora d'esquerres a ERC/PSC. I tant reagrupament  com solidaritat es centren en un eix poc practicat: l'autodeterminació definitiva i desacomplexada.

I ara apareix el Partit Pirata de Catalunya (nom provisional [1]), donant resposta al mateix problema.

Els diferents partits pirates que han anat apareixent a europa s'han  creat amb la idea de donar molta més participació i marge de decisió al  ciutadà dia a dia, sense limitar-se a decisions monolítiques i  puntuals cada 4 anys.

Per això una de les bases de pirata.cat és tenir un programa (ideari) clar i senzill, del que parlaré després, i deixar la resta de decisions en mans dels afiliats.

Això faria que un govern de pirata.cat aportés sobretot propostes  basades en l'ideari, algunes proposades per afiliats, i sobretot  acceptés moltes propostes d'altres partits (després de tot, es tracta de  governar entre tots, aquí no hauríem pas de ser enemics sinó la  representació del poble català).

Així doncs, de què va l'ideari pirata? Doncs hi tenim 5 punts:
  • Mantenir i preservar drets i llibertats que es consideren bàsics  i que últimament, amb l'excusa de la lluita contra el terrorisme i la pederàstia s'estàn deixant de banda: la llibertat d'expresió, la presumpció d'innocència i la privacitat són alguns exemples que s'estan deixant enrere amb aquestes excuses.
  • Fomentar i protegir l'ús d'internet. Que sigui considerat un servei  bàsic com l'aigua i l'electricitat, i que se'n protegeixi la neutralitat, per impedir pràctiques on serveis i opinions puguin ser  silenciades pels operadors, o que existeixin diferents internets,  depenent de la capacitat adquisitiva de l'usuari (neutralitat de la  xarxa).
  • Remodelar el sistema de drets d'autors per dur el protagonisme  als usuaris i als creadors, en comptes dels distribuïdors, per tal  d'aconseguir que la cultura sigui un negoci renovat i adaptat al nou  panorama que internet ha creat. I també eliminar polítiques nascudes de  la incapacitat d'adaptar-se, com ha estat el Cànon Digital: (quantes coses  a dir en aquest aspecte).
  • Renovar el sistema de patents, impedir que siguin renovables i que  tinguin un temps d'expiració raonable per a recuperar la inversió però  també per afavorir la evolució tecnològica. Oposició frontal a les patents del software i sobre els éssers vius.
  • Fomentar la democràcia directa i la participació ciutadana.


[1] El nom del Partit Pirata de Catalunya (pirata.cat) és provisional ja que existeix un Partido Pirata  (pirata.es) i la llei ara impedeix crear partits amb noms que puguin dur a confondre's amb partits anteriors, a no ser que es presenti davant de notari un document on el partit antic accepti com a subeditat el nou. I en aquest cas concret, pirata.cat no vol ser cap "edició catalana" de  pirata.es, sinó una "edició catalana" del Partit Pirata Internacional.

diumenge, 5 de setembre del 2010

Petita nota lingüística

Es vé a afirmar el que ja sabíem:

El Valencià és diferent al Català per raons polítiquen, que no acadèmiques.

Per mostra, un botó.