====== OpenGL Pipeline ======
===== OpenGL Pipeline Básico =====
==== Load pixels in memory ====
=== Android version ===
float[] tableVerticesWithTriangles = {
// Triangle 1
0, 0.5f,
-0.5f, 0,
0.5f, 0,
// Triangle 2
0, 0,
0.5f, -0.5f,
-0.5f, -0.5f
};
vertexData = ByteBuffer
.allocateDirect(tableVerticesWithTriangles.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
vertexData.put(tableVerticesWithTriangles);
==== Change the area where we are gonna render ====
@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
glViewport(0, 0, width, height);
}
==== Coding vertex shader ====
attribute vec4 a_Position;
void main()
{
gl_Position = a_Position;
gl_PointSize = 10.0;
}
==== Coding fragment shader ====
precision mediump float;
uniform vec4 u_Color;
void main()
{
gl_FragColor = u_Color;
}
==== Compiling shaders ====
private int compileShader(int type, String shaderCode) {
final int shaderObjectId = glCreateShader(type);
if (shaderObjectId == 0) {
Log.w(TAG, "Could not create new shader.");
return 0;
}
glShaderSource(shaderObjectId, shaderCode);
glCompileShader(shaderObjectId);
final int[] compileStatus = new int[1];
glGetShaderiv(shaderObjectId, GL_COMPILE_STATUS, compileStatus, 0);
Log.v(TAG, "Results of compiling source:" + "\n" + shaderCode + "\n:" + glGetShaderInfoLog(shaderObjectId));
if (compileStatus[0] == 0) {
glDeleteShader(shaderObjectId);
Log.w(TAG, "Compilation of shader failed.");
return 0;
}
Log.w(TAG, "Compilation of shader was good.");
return shaderObjectId;
}
==== Link and use the shader program ====
public int linkProgram(int vertexShaderId, int fragmentShaderId) {
final int programObjectId = glCreateProgram();
if (programObjectId == 0) {
Log.w(TAG, "Could not create new program");
return 0;
}
glAttachShader(programObjectId, vertexShaderId);
glAttachShader(programObjectId, fragmentShaderId);
glLinkProgram(programObjectId);
final int[] linkStatus = new int[1];
glGetProgramiv(programObjectId, GL_LINK_STATUS, linkStatus, 0);
Log.v(TAG, "Results of linking program:\n" + glGetProgramInfoLog(programObjectId));
if (linkStatus[0] == 0) {
glDeleteProgram(programObjectId);
Log.w(TAG, "Linking of program failed.");
return 0;
}
glValidateProgram(programObjectId);
final int[] validateStatus = new int[1];
glGetProgramiv(programObjectId, GL_VALIDATE_STATUS, validateStatus, 0);
Log.v(TAG, "Results of validating program: " + validateStatus[0]
+ "\nLog:" + glGetProgramInfoLog(programObjectId));
if (validateStatus[0] == 0) {
Log.w(TAG, "Validation program failed.");
return 0;
}
return programObjectId;
}
==== Initialize values ====
* Set the color to clear the screen
* Obtain the shaders code in string format
* Link and use the shader program
* As we are working with fixed triangles, assign shader variable values
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
String vertexShaderSource = Utils.ResourcesReader(context, R.raw.vertex);
String fragmentShaderSource = Utils.ResourcesReader(context, R.raw.fragment);
int vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
int fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
program = linkProgram(vertexShader, fragmentShader);
glUseProgram(program);
uColorLocation = glGetUniformLocation(program, U_COLOR);
aPositionLocation = glGetAttribLocation(program, A_POSITION);
vertexData.position(0);
glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,
false, 0, vertexData);
glEnableVertexAttribArray(aPositionLocation);
==== Render ====
glClear(GL_COLOR_BUFFER_BIT);
glUniform4f(uColorLocation, 1.0f, 0f, 0f, 1.0f);
glDrawArrays(GL_TRIANGLES, 0, 3);
glUniform4f(uColorLocation, 0.0f, 0f, 1f, 1.0f);
glDrawArrays(GL_TRIANGLES, 3, 3);
==== Functional examples ====
* {{:wiki2:ogl:two-triangles.zip|}}
===== Color =====
==== Define vertices, color and indexs ====
float[] tableVerticesWithTriangles = {
// x, y r,g,b
0, 0.5f, 1,0,0,
-0.5f, 0, 0,1,0,
0.5f, 0, 0,0,1
};
vertexData = ByteBuffer
.allocateDirect(tableVerticesWithTriangles.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
vertexData.put(tableVerticesWithTriangles);
byte[] tableIndices = {0, 1, 2};
indexArray = ByteBuffer.allocateDirect(3).put(tableIndices);
==== Shaders ====
=== Vertex Shader ===
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main()
{
v_Color = a_Color;
gl_Position = a_Position;
}
=== Fragment Shader ===
precision mediump float;
varying vec4 v_Color;
void main()
{
gl_FragColor = v_Color;
}
==== Render ====
* Obtain the attributes location for color and position.
* Write color and position (in this case this step could be performed only once).
* Enable them.
* Draw them.
// next step is really important in java
vertexData.position(0);
indexArray.position(0);
glClear(GL_COLOR_BUFFER_BIT);
aColorLocation = glGetAttribLocation(program, A_COLOR);
aPositionLocation = glGetAttribLocation(program, A_POSITION);
glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,
false, STRIDE, vertexData);
glEnableVertexAttribArray(aPositionLocation);
vertexData.position(POSITION_COMPONENT_COUNT);
glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GL_FLOAT,
false, STRIDE, vertexData);
glEnableVertexAttribArray(aColorLocation);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, indexArray);
glDisableVertexAttribArray(aPositionLocation);
glDisableVertexAttribArray(aColorLocation);
=== Constant values ===
private static final int BYTES_PER_FLOAT = 4;
private static final int POSITION_COMPONENT_COUNT = 2;
private static final int COLOR_COMPONENT_COUNT = 3;
private static final int STRIDE = (POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT) * BYTES_PER_FLOAT;
==== Example ====
{{:wiki2:ogl:color.zip|Example}}
===== Transformaciones y proyecciones =====
* {{:wiki2:ogl:tutorial_3_matrices.pdf|Explicacion de matrices y proyecciones}}
* {{:wiki2:ogl:objectoriented.matrix.zip|Ejemplo de matrices y orientación a objetos en OpenGL ES}}
===== Texturas =====
==== Cargar texturas ====
- Read the texture.
- Bind the texture.
- Set filtering: a default must be set, or the texture will be black.
- Load the bitmap into the bound texture with ''texImage2D''.
- Unbind from the texture with ''glBindTexture(GL_TEXTURE_2D, 0)''.
public static int loadTexture(Context context, int resourceId) {
final int[] textureObjectIds = new int[1];
glGenTextures(1, textureObjectIds, 0);
if (textureObjectIds[0] == 0) {
Log.w(TAG, "Could not generate a new OpenGL texture object.");
return 0;
}
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
if (bitmap == null) {
Log.w(TAG, "Resource ID " + resourceId + " could not be decoded.");
glDeleteTextures(1, textureObjectIds, 0);
return 0;
}
glBindTexture(GL_TEXTURE_2D, textureObjectIds[0]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
glBindTexture(GL_TEXTURE_2D, 0);
bitmap.recycle();
Log.w(TAG, "Texture loaded");
return textureObjectIds[0];
}
Podríamos cargar mipmaps:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
==== Shaders ====
=== Vertex ===
attribute vec4 a_Position;
attribute vec2 a_TextureCoordinates;
varying vec2 v_TextureCoordinates;
void main()
{
v_TextureCoordinates = a_TextureCoordinates;
gl_Position = a_Position;
}
=== Fragment ===
precision mediump float;
uniform sampler2D u_TextureUnit;
varying vec2 v_TextureCoordinates;
void main()
{
gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);
}
==== When render ====
vertexData.position(0);
indexArray.position(0);
glClear(GL_COLOR_BUFFER_BIT);
glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,
false, STRIDE, vertexData);
vertexData.position(POSITION_COMPONENT_COUNT);
glVertexAttribPointer(aTextCoordLocation, TEXTURE_COORDINATES_COMPONENT_COUNT, GL_FLOAT,
false, STRIDE, vertexData);
glEnableVertexAttribArray(aPositionLocation);
glEnableVertexAttribArray(aTextCoordLocation);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(uTextureUnitLocation, 0);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, indexArray);
glDisableVertexAttribArray(aPositionLocation);
glDisableVertexAttribArray(aTextCoordLocation);
Setting these values:
float[] tableVerticesWithTriangles = {
// x, y s,t
0, 0.5f, 0.5f,0,
-0.5f, 0, 0,1,
0.5f, 0, 1,1
};
And these constants:
private static final int BYTES_PER_FLOAT = 4;
private static final int POSITION_COMPONENT_COUNT = 2;
private static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2;
private static final int STRIDE = (POSITION_COMPONENT_COUNT + TEXTURE_COORDINATES_COMPONENT_COUNT) * BYTES_PER_FLOAT;
==== Code ====
* {{:wiki2:ogl:textures.zip|}}
===== Luces =====