I am working on a project in which I am using GLES20 to render a texture. I used GLUtils.texImage2D() to draw 2d texture image from the bitmap.
What do I need to implement to make these changes:
Place the texture to the right corner of the screen instead of stretching it to the full screen.
Provide incremental rotation frame by frame to the texture.
Shaders
private final static String FRAGMENT_SHADER =
"precision mediump float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform lowp sampler2D sTexture;\n" +
"uniform lowp sampler2D oTexture;\n" +
"void main() {\n" +
" lowp vec4 textureColor = texture2D(sTexture, vTextureCoord);\n" +
" lowp vec4 textureColor2 = texture2D(oTexture, vTextureCoord);\n" +
" \n" +
" gl_FragColor = mix(textureColor, textureColor2, textureColor2.a);\n" +
"}\n";
protected static final String DEFAULT_VERTEX_SHADER =
"attribute highp vec4 aPosition;\n" +
"attribute highp vec4 aTextureCoord;\n" +
"varying highp vec2 vTextureCoord;\n" +
"void main() {\n" +
"gl_Position = aPosition;\n" +
"vTextureCoord = aTextureCoord.xy;\n" +
"}\n";
Texture Generation
int[] textures = new int[1];
#Override
public void setup() {
super.setup();// 1
GLES20.glGenTextures(1, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
}
#Override
public void onDraw() {
if (bitmap == null) {
return;
}
int offsetDepthMapTextureUniform = getHandle("oTexture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
if (bitmap != null && !bitmap.isRecycled()) {
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap, 0);
}
GLES20.glUniform1i(offsetDepthMapTextureUniform, 3);
// Recycle the bitmap, since its data has been loaded into OpenGL.
releaseBitmap();
}
UPDATED
I added the mMVPMatrix for the texture transformation as suggested by alexrnov. Both, camera feed and overlay texture are rotating now.
protected static final String VERTEX_SHADER ="attribute highp vec4 aPosition;\n" +
"uniform mat4 uMVPMatrix;\n" +
"attribute highp vec4 aTextureCoord;\n" +
"varying highp vec2 vTextureCoord;\n" +
"void main() {\n" +
"gl_Position = uMVPMatrix * aPosition;\n" +
"vTextureCoord = aTextureCoord.xy;\n" +
"}\n";
#Override
public void onDraw() {
....
Matrix.setIdentityM(mvpMatrix, 0);
Matrix.rotateM(mvpMatrix, 0, rotation, 0.0f, 0.0f, 1.0f);
rotation++;
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, getMVPMatrixAsFloatBuffer(mvpMatrix));
...
}
The project structure is quite complicated. I can't write all the code here. Please refer the Github Project
Maybe there is another way, but you can overlay the texture on the rectangle, and apply transformations (movement/rotate) to this rectangle:
Vertex shader:
#version 100
uniform mat4 u_mvpMatrix; // MVP-matrix for moving and rotating texture
attribute vec4 a_position; // data of vertices rectangle
attribute vec2 a_textureCoordinates;
varying vec2 v_textureCoordinates;
void main() {
v_textureCoordinates = a_textureCoordinates;
gl_Position = u_mvpMatrix * a_position;
}
Fragment shader:
#version 100
varying vec2 v_textureCoordinates;
uniform sampler2D s_texture;
void main() {
gl_FragColor = texture2D(s_texture, v_textureCoordinates);
}
Approximate Java-code:
private final int textureID;
...
textureID = loadTexture(R.raw.texture);
...
#Override
public void draw() {
GLES20.glUseProgram(programObject);
GLES20.glEnableVertexAttribArray(positionLink);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, VBO[0]);
GLES20.glVertexAttribPointer(positionLink, VERTEX_COMPONENT,
GLES20.GL_FLOAT, false, VERTEX_STRIDE, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glEnableVertexAttribArray(textureCoordinatesLink);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, VBO[1]);
GLES20.glVertexAttribPointer(textureCoordinatesLink, TEXTURE_COMPONENT,
GLES20.GL_FLOAT, false, TEXTURE_STRIDE, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
GLES20.glUniform1i(samplerLink, 0);
GLES20.glUniformMatrix4fv(mvpMatrixLink, 1, false,
RectangleObject3D.getMVPMatrixAsFloatBuffer());
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, VBO[2]);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, NUMBER_INDICES,
GLES20.GL_UNSIGNED_INT, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
GLES20.glDisableVertexAttribArray(positionLink);
GLES20.glDisableVertexAttribArray(textureCoordinatesLink);
}
MVP-matrix:
import android.opengl.Matrix
protected val viewMatrix = FloatArray(16)
protected val projectionMatrix = FloatArray(16)
protected val modelMatrix = FloatArray(16)
protected val modelViewMatrix = FloatArray(16)
protected val mvpMatrix = FloatArray(16)
...
Matrix.setLookAtM(viewMatrix, 0, 0f, 0f, 0f,
0f, 0f, -4f, 0f, 1.0f, 0.0f) // camera
...
// parameters different for portrait and landscape orientation screen android
Matrix.frustumM(projectionMatrix, 0, left, right, bottom, top, near, far)
...
fun spotPosition() { // invoke on every frame
Matrix.setIdentityM(modelMatrix, 0)
Matrix.translateM(modelMatrix, 0, x, y, z) // move object
Matrix.rotateM(modelMatrix, 0, angleX, 0.0f, 1.0f, 0.0f) // rotate object
Matrix.scaleM(modelMatrix, 0, 4f, 4f, 4f) // scale object
Matrix.multiplyMM(modelViewMatrix, 0, viewMatrix, 0, modelMatrix, 0)
Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, modelViewMatrix, 0)
}
fun getMVPMatrixAsFloatBuffer(): FloatBuffer = floatBuffer(mvpMatrix)
get FloatBuffer (essential in Java SDK):
public static FloatBuffer floatBuffer(float[] data) {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(data.length * 4)
.order(ByteOrder.nativeOrder());
FloatBuffer returnBuffer = byteBuffer.asFloatBuffer();
returnBuffer.put(data).position(0);
return returnBuffer;
}
Related
I'm trying to implement lookup texture to my live camera preview.Everything looks fine except shine and shadows. The shine appears blueish and shadow sometimes has red spot.
I'm using Grafika's Camera Capture. I have referred GpuImage's Shader. I was able to load second texture (lookup texture) using following load texture function,
public int createTextureObjectN() {
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
GlUtil.checkGlError("glGenTextures");
int texId = textures[0];
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
GlUtil.checkGlError("glBindTexture " + texId);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GlUtil.checkGlError("glTexParameter");
return texId;
}
public int loadTexture(final int resourceId) {
final int texId = createTextureObjectN();
if (texId != 0) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Decode
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeResource(MyApplication.getAppContext().getResources(), resourceId, options);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}
return texId;
}
my vertex shader is
private static final String VERTEX_SHADER =
"uniform mat4 uMVPMatrix;\n" +
"uniform mat4 uTexMatrix;\n" +
"attribute vec4 aPosition;\n" +
"attribute vec4 aTextureCoord;\n" +
"varying vec2 vTextureCoord;\n" +
"void main() {\n" +
" gl_Position = uMVPMatrix * aPosition;\n" +
" vTextureCoord = (uTexMatrix * aTextureCoord).xy;\n" +
"}\n";
and fragment shader is
shown below.
The stexture2 is a lookup and stexture is camera preview frame of dimension 1920x1080
And vTextureCoord is cordinates of camera frames
#extension GL_OES_EGL_image_external : require
uniform samplerExternalOES sTexture;
uniform sampler2D sTexture2;
varying vec2 vTextureCoord;
//uniform vec3 iResolution;
//uniform float iGlobalTime;
//highp float aspectRatio = iResolution[1] / iResolution[0];
lowp float intensity = 1.0;
void main()
{
highp vec4 textureColor = texture2D(sTexture, vTextureCoord);
highp float blueColor = textureColor.b * 63.0;
highp vec2 quad1;
quad1.y = floor(floor(blueColor) / 8.0);
quad1.x = floor(blueColor) - (quad1.y * 8.0);
highp vec2 quad2;
quad2.y = floor(ceil(blueColor) / 8.0);
quad2.x = ceil(blueColor) - (quad2.y * 8.0);
highp vec2 texPos1;
texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);
highp vec2 texPos2;
texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) *textureColor.g);
lowp vec4 newColor1 = texture2D(sTexture2, texPos1);
lowp vec4 newColor2 = texture2D(sTexture2, texPos2);
lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));
gl_FragColor = gl_FragColor = mix(textureColor, vec4(newColor.rgb, textureColor.w), intensity);
}
I have been trying to fix this problem since two weeks , hoping to find solution and also have exhausted google searches with all possible keywords. I am new to opengl, and would request help in this particular part.
Thank you for helping me!
i am trying to combine surface texture(external basically camera feed ) and ordinary texture , when i run this the screen becomes black i tried in galaxy s5,s6 got the same results,searched online but couldn't find any resources for this,Any feedback is welcome.
shaders
private final String vertexShaderCodeCamera ="uniform mat4 uMVPMatrix;" +
"attribute vec4 position;" +
"attribute vec2 inputTextureCoordinate;" +
"varying vec2 textureCoordinate;" +
"attribute vec3 a_normal;"+ //new line
"varying vec3 v_normal;"+//new line
"uniform mat4 u_MVMatrix;" +
"void main()" +
"{" +
" gl_Position = uMVPMatrix * position;" +
"textureCoordinate = inputTextureCoordinate;" +
"v_normal = vec3(u_MVMatrix * vec4(a_normal, 0.0));"+
"}";
private final String fragmentShaderCodeCamera =
"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;" +
"varying vec2 textureCoordinate; \n" +
"uniform samplerExternalOES s_texture; \n" +
"uniform sampler2D Texture;" +
"void main(void) {" +
"gl_FragColor = texture2D(s_texture, textureCoordinate );\n" +
"gl_FragColor = texture2D(Texture, textureCoordinate);" +
"}";
camera draw method:
public void display_Camera(int texture){
GLES20.glUseProgram(cam_mProgram);
GLES20.glActiveTexture(GL_TEXTURE_EXTERNAL_OES);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
cam_mPositionHandle = GLES20.glGetAttribLocation(cam_mProgram, "position");
GLES20.glEnableVertexAttribArray(cam_mPositionHandle);
GLES20.glVertexAttribPointer(cam_mPositionHandle, CAM_COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStrideSquare, vertexBuffer);
cam_mTextureCoordHandle = GLES20.glGetAttribLocation(cam_mProgram, "inputTextureCoordinate");
GLES20.glEnableVertexAttribArray(cam_mTextureCoordHandle);
GLES20.glVertexAttribPointer(cam_mTextureCoordHandle, CAM_COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStrideSquare, textureVerticesBuffer);
cam_mColorHandle = 2;//GLES20.glGetAttribLocation(cam_mProgram, "s_texture");
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(cam_mPositionHandle);
GLES20.glDisableVertexAttribArray(cam_mTextureCoordHandle);
}
model draw method:
public void draw1(float[] mvpMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(cam_mProgram);
// get handle to shape's transformation matrix
mPositionHandle = 0;//GLES20.glGetAttribLocation(cam_mProgram, "vPosition");
// get handle to vertex shader's vPosition member
mMVPMatrixHandle = GLES20.glGetUniformLocation(cam_mProgram, "uMVPMatrix");
MainActivity.checkGLError("glGetUniformLocation");
fsTexture = GLES20.glGetUniformLocation(cam_mProgram, "Texture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glUniform1i(fsTexture, 0);
vsTextureCoord = 1;//GLES20.glGetAttribLocation(cam_mProgram, "texCoord");
mNormalHandle = 3;//GLES20.glGetAttribLocation(cam_mProgram, "a_normal");//new line
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
GLES20.glVertexAttribPointer(vsTextureCoord, COORDS_PER_TEXTURE,
GLES20.GL_FLOAT, false,
TextureStride, texBuffer);
GLES20.glEnableVertexAttribArray(vsTextureCoord);
GLES20.glVertexAttribPointer(mNormalHandle, COORDS_PER_NORMAL, GLES20.GL_FLOAT, false,
12, normalbuffer);//new line
GLES20.glEnableVertexAttribArray(mNormalHandle);//new line
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
MainActivity.checkGLError("glUniformMatrix4fv");
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, tablelamp21NumVerts);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(vsTextureCoord);
GLES20.glDisableVertexAttribArray(mNormalHandle);
}
linking of shaders:
cam_mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
if (cam_mProgram != 0)
{
// Bind the vertex shader to the program.
GLES20.glAttachShader(cam_mProgram, cameravertexShader);
// Bind the fragment shader to the program.
GLES20.glAttachShader(cam_mProgram, camerafragmentShader);
// Bind attributes
GLES20.glBindAttribLocation(cam_mProgram, 0, "position");
GLES20.glBindAttribLocation(cam_mProgram, 1, "inputTextureCoordinate");
GLES20.glBindAttribLocation(cam_mProgram, 2, "s_texture");//new line
GLES20.glBindAttribLocation(cam_mProgram, 3, "a_normal");//new line
// Link the two shaders together into a program.
GLES20.glLinkProgram(cam_mProgram);
// Get the link status.
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(cam_mProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
// If the link failed, delete the program.
if (linkStatus[0] == 0)
{
GLES20.glDeleteProgram(cam_mProgram);
cam_mProgram = 0;
}
}
So I'm trying to learn openGLES 2.0 and create a textured rectangle. Apparently I didn't follow all the instructions and now I've ended up with just a odd color square.
heres my shaders.
final String vertexShader =
"uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix.
+ "attribute vec2 a_TexCoordinate;\n" // Per-vertex texture coordinate information we will pass in.
+ "attribute vec4 a_Position; \n" // Per-vertex position information we will pass in.
// + "attribute vec4 a_Color; \n" // Per-vertex color information we will pass in.
// + "varying vec4 v_Color; \n" // This will be passed into the fragment shader.
+ "varying vec2 v_TexCoordinate; \n" // This will be passed into the fragment shader.
+ "void main() \n" // The entry point for our vertex shader.
+ "{ \n"
+ " v_TexCoordinate = a_TexCoordinate;\n" // Pass the texture coordinate through to the fragment shader.
// It will be interpolated across the triangle.
+ " gl_Position = u_MVPMatrix \n" // gl_Position is a special variable used to store the final position.
+ " * a_Position; \n" // Multiply the vertex by the matrix to get the final point in
+ "} \n";
final String fragmentShader =
"precision mediump float; \n" // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
+ "uniform sampler2D u_Texture; \n" // The input texture.
+ "uniform vec4 u_Color; \n" // This is the color from the vertex shader interpolated across the
// triangle per fragment.
+ "varying vec2 v_TexCoordinate; \n" // Interpolated texture coordinate per fragment.
+ "void main() \n" // The entry point for our fragment shader.
+ "{ \n"
+ " gl_FragColor = texture2D(u_Texture, v_TexCoordinate); \n"
+ "} \n";
Here is the load texture function
public static int loadTexture(final Context context, final int resourceId)
{
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0)
{
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}
if (textureHandle[0] == 0)
{
throw new RuntimeException("Error loading texture.");
}
return textureHandle[0];
}
And here is the drawFrame
#Override
public void onDrawFrame(GL10 gl) {
// Set the background clear color to gray.
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
mTextureUniformHandle = GLES20.glGetUniformLocation(programHandle, "u_Texture");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(programHandle, "a_TexCoordinate");
// Set the active texture unit to texture unit 0.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
// Bind the texture to this unit.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
GLES20.glUniform1i(mTextureUniformHandle, 0);
// Draw the triangle facing straight on.
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, Fields.screen_width / 2, Fields.screen_height / 2, 0);
Matrix.scaleM(mModelMatrix, 0, Fields.screen_width / 4, Fields.screen_width / 4, 0);
drawTriangle(mTriangle1Vertices);
}
Any advice for getting rid of the wierd brown square and actually displaying the texture?
Edit: Here are the texture coordinates
public GL20Renderer(Context context) {
final float[] triangle1VerticesData = {
// X, Y, Z,
// R, G, B, A
-1f, 1f, 0.0f,
-1, -1, 0.0f,
1f, 1f, 0.0f,
-1f, -1f, 0.0f,
1f, -1f, 0.0f,
1f, 1f, 0.0f,
};
// Initialize the buffers.
mTriangle1Vertices = ByteBuffer.allocateDirect(triangle1VerticesData.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangle1Vertices.put(triangle1VerticesData).position(0);
final float[] triangle1TextureCoordinateData =
{
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
mTriangleTextureCoordinates = ByteBuffer.allocateDirect(triangle1TextureCoordinateData.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangleTextureCoordinates.put(triangle1TextureCoordinateData).position(0);
this.context = context;
}
and here is the drawtriangle function
private void drawTriangle(final FloatBuffer aTriangleBuffer)
{
// Pass in the position information
aTriangleBuffer.position(mPositionOffset);
GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false,
mStrideBytes, aTriangleBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
int colorHandle = GLES20.glGetUniformLocation(programHandle, "u_Color");
// Set color for drawing the triangle
GLES20.glUniform4f(colorHandle, 0.0f, 0.8f, 1.0f, 1.0f);
// This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix
// (which currently contains model * view).
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix
// (which now contains model * view * projection).
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}
Your drawTriangle code doesn't set the texture co-ordinates anywhere. Add some code something like this:
triangle1TextureCoordinateData.position(mPositionOffset * 2 / 3);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, 2, GLES20.GL_FLOAT, false,
0, triangle1TextureCoordinateData);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
Note you can set the stride to zero if your data is packed in the buffer.
I'm encoding a video using this example EncodeAndMuxTest.java. Instead of generate surface frame by GLES20.glScissor(), i'm drawing a texture (by GLES20.glActiveTexture(), GLES20.glBindTexture(), GLES20.glDrawElements()). But the output video always having black screen.
I recogize that the output video only display color in GLES20.glClear() and it doesn't display image texture. I guess that having some problem with texture when using EGL14.eglSwapBuffers but i cann't figure it out.
Please kindly help me solve my problem. Thanks so much!
Update Code use for example
public void testEncodeVideoToMp4() {
// QVGA at 2Mbps
mWidth = 320;
mHeight = 240;
mBitRate = 2000000;
try {
prepareEncoder();
setupTexture(); // insert new function to setup opengles
mInputSurface.makeCurrent();
for (int i = 0; i < NUM_FRAMES; i++) {
drainEncoder(false);
// Generate a new frame of input.
// generateSurfaceFrame(i);
drawTexture(); // insert new function to draw texture
mInputSurface.setPresentationTime(computePresentationTimeNsec(i));
if (VERBOSE)
Log.d(TAG, "sending frame " + i + " to encoder");
mInputSurface.swapBuffers();
}
drainEncoder(true);
} finally {
releaseEncoder();
}
}
setupTexture() function:
public void setupTexture() {
mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
mVertices.put(mVerticesData).position(0);
mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
mIndices.put(mIndicesData).position(0);
String vShaderStr = "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
String fShaderStr = "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_baseMap; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = texture2D( s_baseMap, v_texCoord ); \n"
+ "} \n";
// Load the shaders and get a linked program object
mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
// Get the attribute locations
mPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_position");
mTexCoordLoc = GLES20.glGetAttribLocation(mProgramObject, "a_texCoord");
// Get the sampler locations
mBaseMapLoc = GLES20.glGetUniformLocation(mProgramObject, "s_baseMap");
// Load the texture
mBaseMapTexId = loadTexture();
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glViewport(0, 0, 720, 1280);
}
loadTexture() function
private int loadTexture() {
int[] textureId = new int[1];
Bitmap bitmap;
bitmap = BitmapFactory.decodeFile(mFilePath); // please change mFilePath to image file in sdcard
if (bitmap == null) {
return -1;
}
GLES20.glGenTextures(1, textureId, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
bitmap.recycle();
return textureId[0];
}
drawTexture() function:
public void drawTexture() {
GLES20.glClearColor(TEST_R0 / 255.0f, TEST_G0 / 255.0f, TEST_B0 / 255.0f, 1.0f); // green color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Use the program object
GLES20.glUseProgram(mProgramObject);
// Load the vertex position
mVertices.position(0);
GLES20.glVertexAttribPointer(mPositionLoc, 3, GLES20.GL_FLOAT, false, 5 * 4, mVertices);
// Load the texture coordinate
mVertices.position(3);
GLES20.glVertexAttribPointer(mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 5 * 4, mVertices);
GLES20.glEnableVertexAttribArray(mPositionLoc);
GLES20.glEnableVertexAttribArray(mTexCoordLoc);
// Bind the base map
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBaseMapTexId);
// Set the base map sampler to texture unit to 0
GLES20.glUniform1i(mBaseMapLoc, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, mIndices);
}
Variables use for openGL ES
// Handle to a program object
private int mProgramObject;
// Attribute locations
private int mPositionLoc;
private int mTexCoordLoc;
// Sampler location
private int mBaseMapLoc;
// Texture handle
private int mBaseMapTexId;
// Additional member variables
private FloatBuffer mVertices;
private ShortBuffer mIndices;
private final float[] mVerticesData = { -1f, 1f, 0.0f, // Position 0
0.0f, 0.0f, // TexCoord 0
-1f, -1f, 0.0f, // Position 1
0.0f, 1.0f, // TexCoord 1
1f, -1f, 0.0f, // Position 2
1.0f, 1.0f, // TexCoord 2
1f, 1f, 0.0f, // Position 3
1.0f, 0.0f // TexCoord 3
};
private final short[] mIndicesData = { 0, 1, 2, 0, 2, 3 };
And the video output only display green screen
I need to scale an object in OpenGL|ES 2.0. Shaders:
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
//the matrix must be included as a modifier of gl_Position
" gl_Position = vPosition * uMVPMatrix;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
Projection:
Matrix.orthoM(mProjMatrix,0,
-1.0f, // Left
1.0f, // Right
-1.0f / ratio, // Bottom
1.0f / ratio, // Top
0.01f, // Near
10000.0f);
Drawing setup:
// Set the camera position (View matrix)
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
Actual render:
float[] scale = {5f,5f,1f};
Matrix.scaleM(scale_matrix, 0, scale[0], scale[1], scale[2]);
Matrix.multiplyMM(r_matrix, 0, scale_matrix, 0, mMVPMatrix, 0);
// Combine the rotation matrix with the projection and camera view
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, r_matrix, 0);
And it will not scale. I can see the triangle and I can rotate it. But scaling does not work.
Since vectors are column vectors in OpenGL you have to change the order of the matrix multiplication in your vertex shader:
gl_Position = uMVPMatrix*vPosition;