Skip to content

Translate to spanish #105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: gh-pages
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,47 +14,45 @@ language: es
* TOC
{:toc}

Billboards are 2D elements incrusted in a 3D world. Not a 2D menu on top of everything else; not a 3D plane around which you can turn; but something in-between, like health bars in many games.
Los billboard son elementos 2D incrustados en un mundo 3D. No es un menú 2D encima de todo lo demás; no es un plano 3D alrededor del cual puedes girar; pero algo intermedio, como las barras de salud en muchos juegos.

What's different with billboards is that they are positionned at a specific location, but their orientation is automatically computed so that it always faces the camera.
Lo que es diferente con los billboard es que se colocan en una ubicación específica, pero su orientación se calcula automáticamente para que siempre esté frente a la cámara.



# Solution #1 : The 2D way
# Solucion #1 : El camino 2D

This one is supra-easy.
Esta es superfacil.

Just compute where your point is on screen, and display a 2D text (see Tutorial 11) at this position.
Simplemente calcule la ubicacion de un punto en la pantalla y muestre un texto 2D (consulte el Tutorial 11) en esta posición.

``` cpp
// Everything here is explained in Tutorial 3 ! There's nothing new.
// Todo esto ya fue explicado en el Tutorial 3! No hay nada nuevo.
glm::vec4 BillboardPos_worldspace(x,y,z, 1.0f);
glm::vec4 BillboardPos_screenspace = ProjectionMatrix * ViewMatrix * BillboardPos_worldspace;
BillboardPos_screenspace /= BillboardPos_screenspace.w;

if (BillboardPos_screenspace.z < 0.0f){
// Object is behind the camera, don't display it.
// Los objetos detras de camara no se visualizan.
}
```

Ta-dah !

On the plus side, this method is really easy, and the billboard will have the same size regardless of its distance to the camera. But 2D text is always displayed on top of everything else, and this can/will mess up the rendering and show above other objects.
En el lado positivo, este método es realmente fácil, y el billboard tendrá el mismo tamaño independientemente de su distancia a la cámara. Pero el texto 2D siempre se muestra encima de todo lo demás, y esto puede/arruinar el renderizado y se mostrará sobre otros objetos.



# Solution #2 : The 3D way
# Solucion #2 : El camino 3D

This one is usually better and not much more complicated.
Este suele ser mejor y no es muy complejo.

The goal is to keep the mesh aligned with the camera, even when the camera moves :
El objetivo es mantener la malla alineada con la cámara, incluso cuando la cámara se mueve :

![]({{site.baseurl}}/assets/images/tuto-billboard/2a.gif)


You can view this problem as generating an appropriate Model matrix, even though it's is much simpler than that.
Puede ver este problema como la generación de una matriz Modelo adecuada, aunque es mucho más simple que eso.

The idea is that each corner of the billboard is at the center position, displaced by the camera's up and right vectors :
La idea es que cada esquina del billboard esté en la posición central, desplazada por los vectores hacia arriba y hacia la derecha de la cámara:



Expand All @@ -63,18 +61,19 @@ The idea is that each corner of the billboard is at the center position, displac



Of course, we only know the billboard's center position in world space, so we also need the camera's up/right vectors in world space.
Por supuesto, solo conocemos la posición central de la cartelera en el espacio global, por lo que también necesitamos los vectores arriba / derecha de la cámara en el espacio global.

In camera space, the camera's up vector is (0,1,0). To get it in world space, just multiply this by the matrix that goes from Camera Space to World Space, which is, of course, the inverse of the View matrix.
En el espacio de la cámara, el vector hacia arriba de la cámara es (0,1,0). Para obtenerlo en el espacio global, simplemente multiplique esto por la matriz que va del espacio de la camara al espacio global, que es, por supuesto, la inversa de la matriz de visualización.

An easier way to express the same math is :

Una forma más fácil de expresar lo mismo de forma matemática es:
```

CameraRight_worldspace = {ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]}
CameraUp_worldspace = {ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]}
```

Once we have this, it's very easy to compute the final vertex' position :
Una vez que tenemos esto, es muy fácil calcular la posición final del vértice:

``` glsl
vec3 vertexPosition_worldspace =
Expand All @@ -84,17 +83,17 @@ vec3 vertexPosition_worldspace =
```
{: .highlightglslvs }

* particleCenter_worldspace is, as its name suggests, the billboard's center position. It is specified with an uniform vec3.
* squareVertices is the original mesh. squareVertices.x is -0.5 for the left vertices, which are thus moved towars the left of the camera (because of the *CameraRight_worldspace)
* BillboardSize is the size, in world units, of the billboard, sent as another uniform.
* ParticleCenter_worldspace es, como su nombre lo indica, la posición central de la cartelera. Se especifica con un vec3 uniforme.
* squareVertices es la malla original. squareVertices.x es -0.5 para los vértices izquierdos, que se mueven hacia la izquierda de la cámara (debido al *CameraRight_worldspace)
* BillboardSize es el tamaño, en unidades globales, del billboard, enviada como otro uniforme.

<div><span style="font-size: medium;"><span style="line-height: 24px;">And presto, here's the result. Wasn't this easy ? </span></span><span style="font-size: 16px;"> </span></div>
![]({{site.baseurl}}/assets/images/tuto-billboard/2.gif)




For the record, here's how squareVertices is made :
Para el registro, así es como se hacen squareVertices:

``` cpp
// The VBO containing the 4 vertices of the particles.
Expand All @@ -106,26 +105,25 @@ For the record, here's how squareVertices is made :
};
```

# Solution #3 : The fixed-size 3D way
# Solucion #3 : El Camino del 3D Ajustado

As you can see above, the size of the billboard changes with respect to the camera's distance. This is the expected result in some cases, but in others, such as health bars, you probably want a fixed-size instead.
Como puede ver arriba, el tamaño del billboard cambia con respecto a la distancia de la cámara. Este es el resultado esperado en algunos casos, pero en otros, como las barras de salud, es probable que desee un tamaño fijo.

Since the displacement between the center and a corner must be fixed in screen-space, that's exactly what we're going to do : compute the center's position in screen space, and offset it.
Dado que el desplazamiento entre el centro y una esquina debe fijarse en el espacio de la pantalla, eso es exactamente lo que vamos a hacer: calcular la posición del centro en el espacio de la pantalla y compensarlo.

``` cpp
vertexPosition_worldspace = particleCenter_wordspace;
// Get the screen-space position of the particle's center
// Obtener la posición del espacio de la pantalla del centro de la partícula
gl_Position = VP * vec4(vertexPosition_worldspace, 1.0f);
// Here we have to do the perspective division ourselves.
// Aquí tenemos que hacer la división de perspectiva nosotros mismos.
gl_Position /= gl_Position.w;

// Move the vertex in directly screen space. No need for CameraUp/Right_worlspace here.
// Mueva el vértice directamente en el espacio de la pantalla. No hay necesidad de CameraUp/Right_worlspace derecho aquí.
gl_Position.xy += squareVertices.xy * vec2(0.2, 0.05);
```

Remember that at this stage of the rendering pipeline, you're in Normalized Device Coordinates, so between -1 and 1 on both axes : it's not in pixels.
Recuerde que en esta etapa de la canalización de representación, está en coordenadas normalizadas, por lo tanto, entre -1 y 1 en ambos ejes: no está en píxeles.

If you want a size in pixels, easy : just use (ScreenSizeInPixels / BillboardSizeInPixels) instead of BillboardSizeInScreenPercentage.
Si quieres un tamaño en píxeles, fácil, facil : Solo usa (ScreenSizeInPixels / BillboardSizeInPixels) en vez de BillboardSizeInScreenPercentage.



Expand All @@ -134,11 +132,11 @@ If you want a size in pixels, easy : just use (ScreenSizeInPixels / BillboardSiz



# Solution #4 : Vertical rotation only
# Solucion #4 : Solo rotacion vertical

Some systems model faraway trees and lamps as billboards. But you really, really don't want your tree to be bent : it MUST be vertical. So you need an hybrid system that rotates only around one axis.
Algunos sistemas modelan árboles y lámparas lejanos como billboards. Pero realmente no quieres que tu árbol se doble: DEBE ser vertical. Por lo tanto, necesitas un sistema híbrido que rote solo alrededor de un eje.

Well, this one is left as an exercise to the reader !
Bueno, ¡esto se deja como ejercicio para el lector!



Expand Down
70 changes: 35 additions & 35 deletions es/intermediate-tutorials/tutorial-9-vbo-indexing/index.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
layout: page
status: publish
published: true
title: 'Tutorial 9 : VBO Indexing'
title: 'Tutorial 9 : Indexado VBO'
date: '2011-05-12 19:21:49 +0200'
date_gmt: '2011-05-12 19:21:49 +0200'
categories: [tuto]
Expand All @@ -14,88 +14,88 @@ language: es
* TOC
{:toc}

# The principle of indexing
# El principío del indexado

Until now, when building your VBO, we always duplicated our vertices whenever two triangles shared an edge.
Hasta ahora, al construir un VBO, siempre duplicamos nuestros vértices cada vez que dos triángulos compartían un borde.

In this tutorial, we introduce indexing, which enables to reuse the same vertex over and over again. This is done with an *index buffer*.
En este tutorial, presentamos la indexación, que permite reutilizar el mismo vértice una y otra vez. Esto se hace con un * index buffer *.

![]({{site.baseurl}}/assets/images/tuto-9-vbo-indexing/indexing1.png)


The index buffer contains integers, three for each triangle in the mesh, which reference the various *attribute buffers* (position, colour, UV coordinates, other UV coordinates, normal, ...). It's a little bit like in the OBJ file format, with one huge difference : there is only ONE index buffer. This means that for a vertex to be shared between two triangles, all attributes must be the same.
El índice del búfer contiene números enteros, tres para cada triángulo en la malla, que hacen referencia a los diversos * búferes de atributos * (posición, color, coordenadas UV, otras coordenadas UV, normal, ...). Es un poco como en el formato de archivo OBJ, con una gran diferencia: solo hay UN búfer de índice. Esto significa que para que un vértice se comparta entre dos triángulos, todos los atributos deben ser iguales.

# Shared vs Separate
# Compartido vs separado

Let's take the example of the normals. In this figure, the artist who created these two triangle probably wanted them to represent a smooth surface. We can thus blend the normals of the two triangle into a single vertex normal. For visualization purposes, I added a red line which represents the aspect of the smooth surface.
Tomemos el ejemplo de las normales. En esta figura, el artista que creó estos dos triángulos probablemente quería que representaran una superficie lisa. Así podemos mezclar las normales de los dos triángulos en un solo vértice normal. Para fines de visualización, agregué una línea roja que representa el aspecto de la superficie lisa.

![]({{site.baseurl}}/assets/images/tuto-9-vbo-indexing/goodsmooth.png)


In this second figure however, the artist visibly wanted a "seam", a rough edge. But if we merge the normals, this means that the shader will smoothly interpolate as usual and create a smooth aspect just like before :
En esta segunda figura, sin embargo, el artista quería visiblemente una "costura", un borde áspero. Pero si fusionamos las normales, esto significa que el sombreador se interpolará suavemente como de costumbre y creará un aspecto suave como antes:

![]({{site.baseurl}}/assets/images/tuto-9-vbo-indexing/badmooth.png)


So in this case it's actually better to have two different normals, one for each vertex. The only way to do this in OpenGL is to duplicate the whole vertex, with its whole set of attributes.
Entonces, en este caso, en realidad es mejor tener dos normales diferentes, una para cada vértice. La única forma de hacer esto en OpenGL es duplicar todo el vértice, con todo su conjunto de atributos.

![]({{site.baseurl}}/assets/images/tuto-9-vbo-indexing/spiky.png)


# Indexed VBO in OpenGL
# VBO indexado en OpenGL

Using indexing is very simple. First, you need to create an additional buffer, which you fill with the right indices. The code is the same as before, but now it's an ELEMENT_ARRAY_BUFFER, not an ARRAY_BUFFER.
Usar indexación es muy simple. Primero, debe crear un búfer adicional, que debe completar con los índices correctos. El código es el mismo que antes, pero ahora es un ELEMENT_ARRAY_BUFFER, no un ARRAY_BUFFER.

``` cpp
std::vector<unsigned int> indices;

// fill "indices" as needed
// llenar los "índices" según sea necesario

// Generate a buffer for the indices
// Generar un buffer para los índices.
GLuint elementbuffer;
glGenBuffers(1, &elementbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
```

and to draw the mesh, simply replace glDrawArrays by this :
y para dibujar la malla, simplemente reemplace glDrawArrays por esto:

``` cpp
// Index buffer
// Indice del buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);

// Draw the triangles !
// Dibujar los triangulos !
glDrawElements(
GL_TRIANGLES, // mode
indices.size(), // count
GL_UNSIGNED_INT, // type
(void*)0 // element array buffer offset
GL_TRIANGLES, // modo
indices.size(), // conteo
GL_UNSIGNED_INT, // tipo
(void*)0 // offset de elementos arreglo del buffer
);
```

(quick note : it's better to use "unsigned short" than "unsigned int", because it takes less memory, which also makes it faster)
(nota rápida: es mejor usar "unsigned short" que "unsigned int", porque requiere menos memoria, lo que también lo hace más rápido)

# Filling the index buffer
# Llenar el búfer de índices

Now we actually have a problem. As I said before, OpenGL can only use one index buffer, whereas OBJ (and some other popular 3D formats like Collada) use one index buffer *by attribute*. Which means that we somehow have to convert from N index buffers to 1 index buffer.
Ahora tenemos un problema. Como dije antes, OpenGL solo puede usar un búfer de índices, mientras que OBJ (y algunos otros formatos 3D populares como Collada) usan un búfer de índices * por atributo *. Lo que significa que de alguna manera tenemos que convertir de N buffers de índice a 1 buffer de índice.

The algorithm to do this is as follows :
El algoritmo para hacer esto es el siguiente:
```

For each input vertex
Try to find a similar ( = same for all attributes ) vertex between all those we already output
If found :
A similar vertex is already in the VBO, use it instead !
If not found :
No similar vertex found, add it to the VBO
Por cada vértice de entrada
Tratar de buscar un similar ( = el mismo por todos los atributos ) vértice entre todos aquellos que ya sacamos
Si encuentra :
Un vértice similar ya está en el VBO, ¡úsalo ese!
Si no lo encuentra :
No se encontró un vértice similar, agréguelo a la VBO
```

The actual C++ code can be found in common/vboindexer.cpp. It's heavily commented so if you understand the algorithm above, it should be all right.
El código real de C ++ se puede encontrar en common/vboindexer.cpp. Está muy comentado, por lo que si comprende el algoritmo anterior, debería estar bien.

The criterion for similarity is that vertices' position, UVs and normals should be ** equal. You'll have to adapt this if you add more attributes.
El criterio de similitud es que la posición de los vértices, los rayos UV y las normales deben ser ** iguales. Tendras que adaptar esto si deseas agregar más atributos.

Searching a similar vertex is done with a lame linear search for simplicity. A std::map would be more appropriate for real use.
La búsqueda de un vértice similar se realiza con una simple búsqueda lineal para simplificar. Un std::map sería más apropiado para un uso real.

# Extra : the FPS counter
# Extra : el contador de FPS

It's not directly related to indexing, but it's a good moment to have a look at [the FPS counter](http://www.opengl-tutorial.org/miscellaneous/an-fps-counter/) because we can eventually see the speed improvement of indexing. Other performance tools are available in [Tools - Debuggers](http://www.opengl-tutorial.org/miscellaneous/useful-tools-links/#header-4).
No está directamente relacionado con la indexación, pero es un buen momento para echar un vistazo [el contador de FPS](http://www.opengl-tutorial.org/miscellaneous/an-fps-counter/) porque eventualmente podemos ver la mejora de la velocidad de indexación. Otras herramientas de rendimiento están disponibles en [Tools - Debuggers](http://www.opengl-tutorial.org/miscellaneous/useful-tools-links/#header-4).