Android OpenGL ES 2.0 - Rotation in place - android

I would like to rotate my triangles in Z axis, but I would to do it around the center of the triangle, not the center of the screen. I have researched a lot on that but didn't find any resolution.
Any idea of what could I try to solve it?
public class RendererClass implements Renderer {
FloatBuffer bufferObj1;
FloatBuffer bufferObj2;
int programObj1;
int programObj2;
int positionObj1;
int positionObj2;
int rotationMatrixLocationObj1;
int rotationMatrixLocationObj2;
int colorObj1;
int colorObj2;
float[] rotationMatrixObj1 = new float[16];
float[] rotationMatrixObj2 = new float[16];
#Override
public void onSurfaceCreated(GL10 arg0, EGLConfig config) {
GLES20.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
float[] vertexObj1 = {
-0.8f, 0.8f,
-0.8f, 0.0f,
0.0f, 0.0f
};
float[] vertexObj2 = {
0.8f, 0.8f,
0.8f, 0.0f,
0.0f, 0.0f
};
bufferObj1 = ByteBuffer.allocateDirect(vertexObj1.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexObj1);
bufferObj2 = ByteBuffer.allocateDirect(vertexObj2.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexObj2);
String vssObj1 = "attribute vec4 positionObj1;" +
"uniform mat4 rotationMatrixObj1;" +
"void main(){" +
"gl_Position = rotationMatrixObj1 * positionObj1;" +
"}";
String vssObj2 = "attribute vec4 positionObj2;" +
"uniform mat4 rotationMatrixObj2;" +
"void main(){" +
"gl_Position = rotationMatrixObj2 * positionObj2;" +
"}";
String fssObj1 = "precision mediump float;" +
"uniform vec4 colorObj1;" +
"void main(){" +
"gl_FragColor = colorObj1;" +
"}";
String fssObj2 = "precision mediump float;" +
"uniform vec4 colorObj2;" +
"void main(){" +
"gl_FragColor = colorObj2;" +
"}";
int vsObj1 = glCreateShader(GL_VERTEX_SHADER);
int vsObj2 = glCreateShader(GL_VERTEX_SHADER);
int fsObj1 = glCreateShader(GL_FRAGMENT_SHADER);
int fsObj2 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vsObj1, vssObj1);
glShaderSource(vsObj2, vssObj2);
glShaderSource(fsObj1, fssObj1);
glShaderSource(fsObj2, fssObj2);
glCompileShader(vsObj1);
glCompileShader(vsObj2);
glCompileShader(fsObj1);
glCompileShader(fsObj2);
programObj1 = glCreateProgram();
programObj2 = glCreateProgram();
glAttachShader(programObj1, vsObj1);
glAttachShader(programObj2, vsObj2);
glAttachShader(programObj1, fsObj1);
glAttachShader(programObj2, fsObj2);
glLinkProgram(programObj1);
glLinkProgram(programObj2);
positionObj1 = glGetAttribLocation(programObj1, "positionObj1");
positionObj2 = glGetAttribLocation(programObj2, "positionObj2");
rotationMatrixLocationObj1 = glGetUniformLocation(programObj1, "rotationMatrixObj1");
rotationMatrixLocationObj2 = glGetUniformLocation(programObj2, "rotationMatrixObj2");
colorObj1 = glGetUniformLocation(programObj1, "colorObj1");
colorObj2 = glGetUniformLocation(programObj2, "colorObj2");
}
#Override
public void onSurfaceChanged(GL10 arg0, int width, int height) {
Matrix.setIdentityM(rotationMatrixObj1, 0);
Matrix.rotateM(rotationMatrixObj1, 0, MainActivity.angle, 0, 0, 1);
Matrix.setIdentityM(rotationMatrixObj2, 0);
Matrix.rotateM(rotationMatrixObj2, 0, MainActivity.angle, 0, 0, -1);
}
GL10 gl;
#Override
public void onDrawFrame(GL10 glUnused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
onSurfaceChanged(gl, 0, 0);
glUseProgram(programObj1);
bufferObj1.position(0);
glVertexAttribPointer(positionObj1, 2, GL_FLOAT, false, 0, bufferObj1);
glEnableVertexAttribArray(positionObj1);
glUniform4f(colorObj1, 0.0f, 0.0f, 1.0f, 1.0f);
glUniformMatrix4fv(rotationMatrixLocationObj1, 1, false, rotationMatrixObj1, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glUseProgram(programObj2);
bufferObj2.position(0);
glVertexAttribPointer(positionObj2, 2, GL_FLOAT, false, 0, bufferObj2);
glEnableVertexAttribArray(positionObj2);
glUniform4f(colorObj2, 1.0f, 0.0f, 0.0f, 1.0f);
glUniformMatrix4fv(rotationMatrixLocationObj2, 1, false, rotationMatrixObj2, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
}

You use glDrawArrays so you can alter your triangles in your code any way you want. Use simple trigonometry to rotate your vertices independently.

Rotation matrix rotates vertices around center of coordinate system.
If you want to rotate scene around some other point (x0, y0, z0) you have to do this in 3 simple steps:
translate scene in such way that your point will be in center of coord system (by -x0, -y0, -z0)
rotate
translate back (by x0, y0, z0)
Of course 3 steps of transformation are not needed, matrix multiplication can do this work for us.

Related

android opengl not rendering properly

I am having a problem when rendering a texture to the viewport.
The screen is being rendered but the texture (256*256) does not the same as the original jpg picture I uploaded.
Please find attached images and code for the render. One image is the original jpg and the other is screenshot that is the rendered texture on the android phone.
original
rendered image
This is my MainActivity code:
private void initialize() {
if (hasGLES20()) {
GLSurfaceView mGLView = new GLSurfaceView(this);
mGLView.setEGLContextClientVersion(2);
mGLView.setPreserveEGLContextOnPause(true);
mGLView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
mGLView.setEGLConfigChooser(true);
mGLView.setRenderer(this);
setContentView(mGLView);
}
}
#Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
GLES20.glClearColor(0.5f,0.3f,0.8f,1.0f);
String vertexShaderSource = "" +
"uniform mat4 u_projection;" +
"uniform mat4 u_model;" +
"uniform mat4 u_view;" +
"" +
"attribute vec4 a_position;" +
"attribute vec2 a_texCoord;" +
"" +
"varying vec2 v_texCoord;" +
"" +
"void main()" +
"{" +
" gl_Position = u_projection * u_view * u_model * a_position;" +
" v_texCoord = a_texCoord;" +
"}";
String fragmentShaderSource = "" +
"varying vec2 v_texCoord;" +
"uniform sampler2D s_texture;" +
"" +
"void main() {" +
" vec4 texCol = texture2D(s_texture, v_texCoord );" +
" gl_FragColor = texCol;" +
"}";
texture = new Texture(this);
vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glShaderSource(vertexShader, vertexShaderSource);
GLES20.glCompileShader(vertexShader);
String vertexShaderCompileLog = GLES20.glGetShaderInfoLog(vertexShader);
fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragmentShader, fragmentShaderSource);
GLES20.glCompileShader(fragmentShader);
String fragmentShaderCompileLog = GLES20.glGetShaderInfoLog(fragmentShader);
programID = GLES20.glCreateProgram();
GLES20.glAttachShader(programID,vertexShader);
GLES20.glAttachShader(programID,fragmentShader);
GLES20.glBindAttribLocation(programID, 0, "a_position");
GLES20.glBindAttribLocation(programID, 1, "a_texCoord");
GLES20.glLinkProgram(programID);
String programLinkLog = GLES20.glGetProgramInfoLog(programID);
GLES20.glUseProgram(programID);
float[] modelMatrix = new float[16], viewMatrix = new float[16], projectionMatrix = new float[16];
ByteBuffer modelMatrixByteBuffer = ByteBuffer.allocateDirect(modelMatrix.length * 4);
modelMatrixByteBuffer.order(ByteOrder.nativeOrder());
FloatBuffer modelMatrixBuffer = modelMatrixByteBuffer.asFloatBuffer();
Matrix.setIdentityM(modelMatrix,0);
Matrix.translateM(modelMatrix, 0, modelMatrix,0,0,0,-2.0f);
modelMatrixBuffer.put(modelMatrix);
modelMatrixBuffer.rewind();
// translate model to 0,0,-2
Matrix.setLookAtM(viewMatrix,0,0,0,0,0,0,-10,0,1,0);
Matrix.perspectiveM(projectionMatrix,0,70,256/256,0.1f,100);
GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(programID,"u_projection"),1,false,projectionMatrix,0);
GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(programID,"u_view"),1,false,viewMatrix,0);
GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(programID,"u_model"),1,false,modelMatrixBuffer);
}
#Override
public void onSurfaceChanged(GL10 gl10, int width, int height) {
GLES20.glViewport(0,0,256,256);
}
#Override
public void onDrawFrame(GL10 gl10){
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
float vertices[] =
{
-1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f
};
float textureCoord[] =
{
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
};
ByteBuffer verticesByteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
verticesByteBuffer.order(ByteOrder.nativeOrder());
FloatBuffer verticesBuffer = verticesByteBuffer.asFloatBuffer();
verticesBuffer.put(vertices);
verticesBuffer.rewind();
ByteBuffer textureCoordByteBuffer = ByteBuffer.allocateDirect(textureCoord.length * 4);
textureCoordByteBuffer.order(ByteOrder.nativeOrder());
FloatBuffer textureCoordBuffer = textureCoordByteBuffer.asFloatBuffer();
textureCoordBuffer.put(textureCoord);
textureCoordBuffer.rewind();
GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 3 * 4, verticesBuffer);
GLES20.glVertexAttribPointer(1, 2, GLES20.GL_FLOAT, false, 2 * 4, textureCoordBuffer);
GLES20.glEnableVertexAttribArray(0);
GLES20.glEnableVertexAttribArray(1);
texture.setTexture();
GLES20.glUniform1i(GLES20.glGetUniformLocation(programID,"s_texture"),0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
This is my load Texture Class
public class Texture
{
private int m_iTextureId;
public Texture(Context ctx)
{
m_iTextureId = loadTexture(ctx, R.drawable.index);
}
public void setTexture()
{
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, m_iTextureId);
}
public int loadTexture(Context ctx, int rsrcId)
{
int[] iTextureId = new int[1];
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glGenTextures(1, iTextureId, 0);
if(iTextureId[0] != 0)
{
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, iTextureId[0]);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeResource(ctx.getResources(), rsrcId,
options);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
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);
}
else
{
throw new RuntimeException("Error loading texture");
}
return iTextureId[0];
}
Any help?
Your texture coordinates are wrong. They contain the same coordinate twice:
float textureCoord[] =
{
0.0f, 1.0f, <--
0.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f <--
};
To solve this replace the last coordinate with [1, 0] instead of [0, 1].

Android OpenGL-ES-2.0 Circle or disc

I'm trying to draw a disc in OpenGL-ES 2.0. Based on the second answer to this question How to draw basic circle in OpenGL ES 2.0 Android by user2901066, I'm doing:
String VertexShaderCode ="uniform mat4 uMVPMatrix;\n" +
"attribute vec4 vPosition;\n" +
"void main() {\n" +
"gl_Position = uMVPMatrix * vPosition;\n" +
"}";
String FragmentShaderCode = "precision mediump float;\n" +
"void main() {\n" +
//The problem is here
//"if ((textureCoord.x * textureCoord.x) + (textureCoord.y * textureCoord.y) <= 1.0)" +
"if (true)\n" +
"gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n" +
"else\n" +
"gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 0.0f);\n" +
"}";
int vertexShader = this.loadShader(GLES20.GL_VERTEX_SHADER, VertexShaderCode);
int fragmentShader = this.loadShader(GLES20.GL_FRAGMENT_SHADER, FragmentShaderCode);
mGlProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mGlProgram, vertexShader);
GLES20.glAttachShader(mGlProgram, fragmentShader);
GLES20.glLinkProgram(mGlProgram);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
protected int PositionHandle;
protected int MVPMatrixHandle;
static final int COORDS_PER_VERTEX = 3;
private final int VertexStride = COORDS_PER_VERTEX * 4;
private float LineCoords[] = new float[4 * 3];
private FloatBuffer VertexBuffer;
private final int VertexCount = 4;
ByteBuffer bb = ByteBuffer.allocateDirect(LineCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
VertexBuffer = bb.asFloatBuffer();
VertexBuffer.put(LineCoords);
VertexBuffer.position(0);
float[] mvpMatrix = {1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f};
LineCoords[0] = -1.0f;
LineCoords[1] = 1.0f;
LineCoords[3] = -1.0f;
LineCoords[4] = -1.0f;
LineCoords[6] = 1.0f;
LineCoords[7] = -1.0f;
LineCoords[9] = 1.0f;
LineCoords[10] = 1.0f;
VertexBuffer.put(LineCoords);
VertexBuffer.position(0);
GLES20.glUseProgram(mGlProgram);
PositionHandle = GLES20.glGetAttribLocation(mGlProgram, "vPosition");
GLES20.glEnableVertexAttribArray(PositionHandle);
GLES20.glVertexAttribPointer(PositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, VertexStride, VertexBuffer);
MVPMatrixHandle = GLES20.glGetUniformLocation(mGlProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, VertexCount);
GLES20.glDisableVertexAttribArray(PositionHandle);
My problem is to get the position in the fragment shader in order to apply the right color. How do I do that?
You need a varying variable declared on both shaders:
varying vec2 textureCoord;
then on the vertex shader, put some value to it such as:
textureCoord = gl_Position.xy;
this variable will then be sent to the fragment shader interpolated for each fragment so your fragment shader can use it:
if ((textureCoord.x * textureCoord.x) + (textureCoord.y * textureCoord.y) <= 1.0)
{
gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
} else {
gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 0.0f);
}

OpenGL ES 2.0 diffuse lighting: model shows up black

This problem bothers me for about a week...
I tried to load stl files and show it on the screen. The file was read properly. Rendering without adding light was pretty good. After I add lighting and shader codes, the model is still there but turns out black.
I followed the example downloaded from link below this article:
http://www.learnopengles.com/android-lesson-two-ambient-and-diffuse-lighting/
The shader code was completely as the same as the example. The program links fine. The Shaders compile fine, too. I can't find out where the problem is. PLZ help me.
My Renderer:
public class MyGLRenderer implements GLSurfaceView.Renderer {
private Test test;
private Light1 light1;
private float range = 145;
private final float[] mMVMMatrix = new float[16];
private final float[] mMVPMatrix = new float[16];
private final float[] mModelMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
protected final static float[] mLightPosInEyeSpace = new float[4];
private final float[] mLightModelMatrix = new float[16];
private final float[] mLightPosInModelSpace = new float[] {0.0f, 0.0f, 0.0f, 1.0f};
private final float[] mLightPosInWorldSpace = new float[4];
private final float[] mTempMatrix = new float[16];
public static final float[] mAccumulatedMatrix = new float[16];
private final float[] mCurrMatrix = new float[16];
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthFunc(GLES20.GL_LEQUAL);
Matrix.setIdentityM(mTempMatrix, 0);
Matrix.setIdentityM(mAccumulatedMatrix, 0);
light1 = new Light1();
test = new Test();
}
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setIdentityM(mViewMatrix, 0);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.setIdentityM(mCurrMatrix, 0);
Matrix.setIdentityM(mLightModelMatrix, 0);
Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0, mLightPosInModelSpace, 0);
Matrix.multiplyMV(mLightPosInEyeSpace, 0, mViewMatrix, 0, mLightPosInWorldSpace, 0);
Matrix.rotateM(mCurrMatrix, 0, mAngleY, 0.0f, 1.0f, 0.0f);
Matrix.rotateM(mCurrMatrix, 0, mAngleX, 1.0f, 0, 0.0f);
mAngleX = 0.0f;
mAngleY = 0.0f;
Matrix.multiplyMM(mTempMatrix, 0, mCurrMatrix, 0, mAccumulatedMatrix, 0);
System.arraycopy(mTempMatrix, 0, mAccumulatedMatrix, 0, 16);
Matrix.multiplyMM(mTempMatrix, 0, mModelMatrix, 0, mAccumulatedMatrix, 0);
System.arraycopy(mTempMatrix, 0, mModelMatrix, 0, 16);
Matrix.translateM(mModelMatrix, 0, -test.meanX, -test.meanY, -test.meanZ);
Matrix.multiplyMM(mMVMMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVMMatrix, 0);
light1.draw(mMVPMatrix);
test.draw(mMVPMatrix, mMVMMatrix);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.orthoM(mProjectionMatrix, 0, -range*ratio, range*ratio, -range, range, -range, range);
}
public final static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public static volatile float mAngleX;
public static volatile float mAngleY;
public static void setAngleX(float angle) {mAngleX = angle;}
public float getAngleX() {
return mAngleX;
}
public static void setAngleY(float angle) {
mAngleY = angle;
}
public float getAngleY() {
return mAngleY;
}}
My code to draw where the light is:
public class Light1 {
private final String vertexShaderCode =
"uniform mat4 u_MVPMatrix; \n"
+ "attribute vec4 a_Position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_MVPMatrix \n"
+ " * a_Position; \n"
+ " gl_PointSize = 5.0; \n"
+ "} \n";
private final String fragmentShaderCode =
"precision mediump float; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4(1.0, \n"
+ " 1.0, 1.0, 1.0); \n"
+ "} \n";
//Light*******************
public static float[] lightLocation = new float[] {150, 150, 0};//*********ok
private final int mProgram;
//Light*******************
public Light1() {
// initialize byte buffer for the draw list
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
}
public void draw(float[] mvpMatrix) {
GLES20.glUseProgram(mProgram);
final int pointMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");
final int pointPositionHandle = GLES20.glGetAttribLocation(mProgram, "a_Position");
GLES20.glVertexAttrib3f(pointPositionHandle, lightLocation[0], lightLocation[1], lightLocation[2]);
GLES20.glUniformMatrix4fv(pointMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
GLES20.glDisableVertexAttribArray(pointPositionHandle);
}}
My Model Code:
public class Test {
final String vertexShaderCode =
"uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix.
+ "uniform mat4 u_MVMatrix; \n" // A constant representing the combined model/view matrix.
+ "uniform vec3 u_LightPos; \n" // The position of the light in eye space.
+ "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.
+ "attribute vec3 a_Normal; \n" // Per-vertex normal information we will pass in.
+ "varying vec4 v_Color; \n" // This will be passed into the fragment shader.
+ "void main() \n" // The entry point for our vertex shader.
+ "{ \n"
// Transform the vertex into eye space.
+ " vec3 modelViewVertex = vec3(u_MVMatrix * a_Position); \n"
// Transform the normal's orientation into eye space.
+ " vec3 modelViewNormal = vec3(u_MVMatrix * vec4(a_Normal, 0.0)); \n"
// Will be used for attenuation.
+ " float distance = length(u_LightPos - modelViewVertex); \n"
// Get a lighting direction vector from the light to the vertex.
+ " vec3 lightVector = normalize(u_LightPos - modelViewVertex); \n"
// Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
// pointing in the same direction then it will get max illumination.
+ " float diffuse = max(dot(modelViewNormal, lightVector), 0.1); \n"
// Attenuate the light based on distance.
+ " diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance))); \n"
// Multiply the color by the illumination level. It will be interpolated across the triangle.
+ " v_Color = a_Color * diffuse; \n"
// gl_Position is a special variable used to store the final position.
// Multiply the vertex by the matrix to get the final point in normalized screen coordinates.
+ " gl_Position = u_MVPMatrix * a_Position; \n"
+ "} \n";
private final String fragmentShaderCode =
"precision mediump float; \n" // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
+ "varying vec4 v_Color; \n" // This is the color from the vertex shader interpolated across the
// triangle per fragment.
+ "void main() \n" // The entry point for our fragment shader.
+ "{ \n"
+ " gl_FragColor = v_Color; \n" // Pass the color directly through the pipeline.
+ "} \n";
private FloatBuffer vertexBuffer;
private FloatBuffer colorBuffer;
private FloatBuffer normalBuffer;
private final int mProgram;
private int mPositionHandle;
private int mNormalHandle;
private int mLightLocationHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
private int mMVMatrixHandle;
final int COORDS_PER_VERTEX = 3;
float[] squareCoords;
float[] coordsNormals;
float color[];
public Test() {
squareCoords = GlassUI10.ReadStlBinary("test.stl");
coordsNormals = VectorCalculate.getNormByPtArray(squareCoords);
color = new float[squareCoords.length/3*4];
for(int i = 0; i < color.length/4 ; i = i+4)
{
color[i+0] =0.3f;
color[i+1] =0.7f;
color[i+2] =0.6f;
color[i+3] =1.3f;
}
System.gc();
Log.v("TestLoaded: ", "Loaded");
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
colorBuffer = ByteBuffer.allocateDirect(color.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
colorBuffer.put(color).position(0);
ByteBuffer nb = ByteBuffer.allocateDirect(coordsNormals.length * 4);
nb.order(ByteOrder.nativeOrder());
normalBuffer = nb.asFloatBuffer();
normalBuffer.put(coordsNormals);
normalBuffer.position(0);
// initialize byte buffer for the draw list
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);//*********ok
int fragmentShader = MyGLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);//*********ok
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glBindAttribLocation(mProgram, 0, "a_Position");
GLES20.glBindAttribLocation(mProgram, 1, "a_Color");
GLES20.glBindAttribLocation(mProgram, 2, "a_Normal");
GLES20.glLinkProgram(mProgram);
}
public void draw(float[] mvpMatrix, float[] mvMatrix) {
GLES20.glUseProgram(mProgram);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");
mMVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVMatrix");
mLightLocationHandle = GLES20.glGetUniformLocation(mProgram, "u_LightPos");
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "a_Position");
mColorHandle = GLES20.glGetUniformLocation(mProgram, "a_Color");
mNormalHandle = GLES20.glGetAttribLocation(mProgram, "a_Normal");
vertexBuffer.position(0);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
colorBuffer.position(0);
GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false, 0, colorBuffer);
GLES20.glEnableVertexAttribArray(mColorHandle);
normalBuffer.position(0);
GLES20.glVertexAttribPointer(mNormalHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, normalBuffer);
GLES20.glEnableVertexAttribArray(mNormalHandle);
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mvMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glUniform3f(mLightLocationHandle, MyGLRenderer.mLightPosInEyeSpace[0], MyGLRenderer.mLightPosInEyeSpace[1], MyGLRenderer.mLightPosInEyeSpace[2]);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, squareCoords.length/COORDS_PER_VERTEX); GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}}
Any answer will be appreciated!
I fixed the problem.
First. The color-given loop was wrong. Be fixed below:
for(int i = 0; i < color.length ; i = i+4)
It caused only few surface being colored; But this was not the main point to cause the model being black;
The main point is that the distance in diffuse light formula is to big; It cause the diffuse to become a very small value which cause the color RGB goes extremely close to zero;
" diffuse = diffuse * (1.0 / (1.0 + (0.00000025 * distance * distance)));"
It need a better formula, but simply decrease the value of distance should show the color and light affect.
In your code, the COORDS_PER_VERTEX is 3. But in your shader code "attribute vec4 a_Position; \n", the a_Position is vec4.
So GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, vertexBuffer); has incompatible vector size.

Activating/using GL_TEXTURE1 at OpenGL ES 2.0 for Android

I'm trying to use the GL_TEXTURE1 texture unit to draw a simple shape. I know how to draw it using the standard GL_TEXTURE0, but when changing it something is not working.
I thought that from my code below, I just had to change the following:
glActiveTexture(GL_TEXTURE1);
glUniform1i(uTextureLocation, 1);
What I'm missing?
Code:
public class RendererClass implements Renderer {
Context context;
FloatBuffer verticesInBuffer;
int aPositionLocation;
int aTextureLocation;
int uTextureLocation;
int program;
public RendererClass(Context context){
this.context = context;
}
#Override
public void onSurfaceCreated(GL10 arg0, EGLConfig config) {
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
float[] vertices = {
-0.5f, 0.5f, 0.5f, 0.5f,
-1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, 0.0f, 0.0f, 0.0f
};
verticesInBuffer = ByteBuffer.allocateDirect(vertices.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertices);
String vss = "attribute vec4 a_Position;" +
"attribute vec2 a_Texture;" +
"varying vec2 v_Texture;" +
"void main(){" +
" v_Texture = a_Texture;" +
" gl_Position = a_Position;" +
"}";
String fss = "precision mediump float;" +
"varying vec2 v_Texture;" +
"uniform sampler2D u_Texture;" +
"void main(){" +
" gl_FragColor = texture2D(u_Texture, v_Texture);" +
"}";
int vs = glCreateShader(GL_VERTEX_SHADER);
int fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vs, vss);
glShaderSource(fs, fss);
glCompileShader(vs);
glCompileShader(fs);
program = glCreateProgram();
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
aPositionLocation = glGetAttribLocation(program, "a_Position");
// ***** Texture stuff starts here </</</</
// Fase 1
glActiveTexture(GL_TEXTURE0);
int[] genTextures = new int[1];
glGenTextures(1, genTextures, 0);
glBindTexture(GL_TEXTURE_2D, genTextures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Fase 2
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bitmap1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.res_for_test_1, options);
// Fase 3
texImage2D(GL_TEXTURE_2D, 0, bitmap1, 0);
glGenerateMipmap(GL_TEXTURE_2D);
// Fase 4
aTextureLocation = glGetAttribLocation(program, "a_Texture");
uTextureLocation = glGetUniformLocation(program, "u_Texture");
glUniform1i(uTextureLocation, 0);
verticesInBuffer.position(2);
glEnableVertexAttribArray(aTextureLocation);
glVertexAttribPointer(aTextureLocation, 2, GL_FLOAT, false, 16, verticesInBuffer);
// ***** Texture stuff ends here </</</</
}
#Override
public void onSurfaceChanged(GL10 arg0, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
#Override
public void onDrawFrame(GL10 glUnused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
glUseProgram(program);
verticesInBuffer.position(0);
glEnableVertexAttribArray(aPositionLocation);
glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, false, 16, verticesInBuffer);
glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
}
}
You need to specify active texture unit and assign a previously loaded texture to it.
For convenience, I've created a helper function which does all of this. It activates given texture unit, assigns texture with given ID to it and puts this value to sampler2D uniform of shader:
protected void setTexture2D(int textureUnit, int textureID, int uniformID) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + textureUnit);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
GLES20.glUniform1i(uniformID, textureUnit);
}
And then call it like this:
setTexture2D(0, textureID, uniformID);

Point is not showing in opengles 2.0

I am trying to learn OpenGLES 2.0 in android in depth. I am trying to draw a Simple Point at the center of screen but somehow , the point is not showing .
public class MyRenderer implements GLSurfaceView.Renderer {
Context context;
private int mProgram;
private final float[] mViewMatrix=new float[16];
private float[] mProjectionMatrix=new float[16];
private final float[] mPointModelMatrix=new float[16];
private final float[] mMVPMatrix=new float[16];
private final float[] mPointPosInModelSpace = new float[] {0.0f, 0.0f, 0.0f, 1.0f};
private final float[] mPointPosInWorldSpace = new float[4];
private final float[] mPointPosInEyeSpace = new float[4];
private int pointMVPMatrixHandle;
private int pointPositionHandle;
public MyRenderer(Context context){
this.context=context;
}
public void onDrawFrame(GL10 arg0) {
// TODO Auto-generated method stub
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Matrix.setIdentityM(mPointModelMatrix, 0);
Matrix.translateM(mPointModelMatrix, 0, 0.0f, 0.0f, -3.0f);
Matrix.multiplyMV(mPointPosInWorldSpace, 0, mPointModelMatrix, 0, mPointPosInModelSpace, 0);
Matrix.multiplyMV(mPointPosInEyeSpace, 0, mViewMatrix, 0, mPointPosInWorldSpace, 0);
GLES20.glUseProgram(mProgram);
drawPoint();
}
private void drawPoint(){
pointMVPMatrixHandle=GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");
pointPositionHandle=GLES20.glGetAttribLocation(mProgram, "a_position");
GLES20.glVertexAttrib3f(pointPositionHandle, mPointPosInEyeSpace[0], mPointPosInEyeSpace[1], mPointPosInEyeSpace[2]);
GLES20.glDisableVertexAttribArray(pointPositionHandle);
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mPointModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(pointMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Draw the point.
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
GLES20.glViewport(0, 0, width, height);
final float ratio=(float)width/height;
Log.d("Ratio is", " "+ratio);
Log.d("Width is"," "+width+" and "+height);
final float left = -ratio;
final float right = ratio;
final float bottom= -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 10.0f;
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
float eyeX=0.0f;
float eyeY=0.0f;
float eyeZ=-0.5f;
float centerX=0.0f;
float centerY=0.0f;
float centerZ=-5.0f;
float upX=0.0f;
float upY=1.0f;
float upZ=0.0f;
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
final String vertexShader=this.getVertexShader();
final String fragmentShader=this.getFragmentShader();
final int vertexShaderHandle=ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);
final int fragmentShaderHandle=ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
mProgram=ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, new String[]{"a_position"});
}
private String getVertexShader(){
final String vertexShader="uniform mat4 u_MVPMatrix; \n"
+ "attribute vec4 a_Position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_MVPMatrix \n"
+ " * a_Position; \n"
+ " gl_PointSize = 10.0; \n"
+ "} \n";
return vertexShader;
}
private String getFragmentShader(){
final String fragmentShader="precision mediump float; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4(1.0, \n"
+ " 1.0, 1.0, 1.0); \n"
+ "} \n";
return fragmentShader;
}
}
I am pretty much sure that I am pointing the both eye and point in negative Z direction(further from viewer) . The point should show up as in vertex Shader, point size is 10.0 but somehow, no luck.
Note: ShaderHelper is a class with static method compileShader and createAndLinkProgram where code for compiling shaders, checking for errors are written. (No Errors in Program)
Here is a class I built based around your code for displaying the point. Since you will probably use more than one point eventually it is better to push the points into a vertex array as shown.
package point.example.point;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
public class PointRenderer implements GLSurfaceView.Renderer
{
private float[] mModelMatrix = new float[16];
private float[] mViewMatrix = new float[16];
private float[] mProjectionMatrix = new float[16];
private float[] mMVPMatrix = new float[16];
private int mMVPMatrixHandle;
private int mPositionHandle;
float[] vertices = {
0.0f,0.0f,0.0f
};
FloatBuffer vertexBuf;
#Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
{
vertexBuf = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuf.put(vertices).position(0);
// Set the background clear color to gray.
GLES20.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
float eyeX=0.0f;
float eyeY=0.0f;
float eyeZ=0.0f;
float centerX=0.0f;
float centerY=0.0f;
float centerZ=-5.0f;
float upX=0.0f;
float upY=1.0f;
float upZ=0.0f;
// Set the view matrix. This matrix can be said to represent the camera position.
// NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
// view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
final String vertexShader =
"uniform mat4 u_MVPMatrix; \n"
+ "attribute vec4 a_Position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_MVPMatrix \n"
+ " * a_Position; \n"
+ " gl_PointSize = 10.0; \n"
+ "} \n";
final String fragmentShader =
"precision mediump float; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4(1.0, \n"
+ " 1.0, 1.0, 1.0); \n"
+ "} \n";
// Load in the vertex shader.
int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
if (vertexShaderHandle != 0)
{
// Pass in the shader source.
GLES20.glShaderSource(vertexShaderHandle, vertexShader);
// Compile the shader.
GLES20.glCompileShader(vertexShaderHandle);
// Get the compilation status.
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// If the compilation failed, delete the shader.
if (compileStatus[0] == 0)
{
GLES20.glDeleteShader(vertexShaderHandle);
vertexShaderHandle = 0;
}
}
if (vertexShaderHandle == 0)
{
throw new RuntimeException("Error creating vertex shader.");
}
// Load in the fragment shader shader.
int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
if (fragmentShaderHandle != 0)
{
// Pass in the shader source.
GLES20.glShaderSource(fragmentShaderHandle, fragmentShader);
// Compile the shader.
GLES20.glCompileShader(fragmentShaderHandle);
// Get the compilation status.
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// If the compilation failed, delete the shader.
if (compileStatus[0] == 0)
{
GLES20.glDeleteShader(fragmentShaderHandle);
fragmentShaderHandle = 0;
}
}
if (fragmentShaderHandle == 0)
{
throw new RuntimeException("Error creating fragment shader.");
}
// Create a program object and store the handle to it.
int programHandle = GLES20.glCreateProgram();
if (programHandle != 0)
{
// Bind the vertex shader to the program.
GLES20.glAttachShader(programHandle, vertexShaderHandle);
// Bind the fragment shader to the program.
GLES20.glAttachShader(programHandle, fragmentShaderHandle);
// Bind attributes
GLES20.glBindAttribLocation(programHandle, 0, "a_Position");
// Link the two shaders together into a program.
GLES20.glLinkProgram(programHandle);
// Get the link status.
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
// If the link failed, delete the program.
if (linkStatus[0] == 0)
{
GLES20.glDeleteProgram(programHandle);
programHandle = 0;
}
}
if (programHandle == 0)
{
throw new RuntimeException("Error creating program.");
}
// Set program handles. These will later be used to pass in values to the program.
mMVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_MVPMatrix");
mPositionHandle = GLES20.glGetAttribLocation(programHandle, "a_Position");
// Tell OpenGL to use this program when rendering.
GLES20.glUseProgram(programHandle);
}
#Override
public void onSurfaceChanged(GL10 glUnused, int width, int height)
{
// Set the OpenGL viewport to the same size as the surface.
GLES20.glViewport(0, 0, width, height);
// Create a new perspective projection matrix. The height will stay the same
// while the width will vary as per aspect ratio.
final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 100.0f;
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}
#Override
public void onDrawFrame(GL10 glUnused)
{
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
Matrix.setIdentityM(mModelMatrix, 0);
//Push to the distance - note this will have no effect on a point size
Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -5.0f);
Matrix.multiplyMV(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMV(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
//Send the vertex
GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuf);
GLES20.glEnableVertexAttribArray(mPositionHandle);
//Draw the point
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
}
}

Categories

Resources