NDK, OpenGL ES ,The first triangle

August 6, 2012   ·   0 Comments

device-2012-08-05-194137

The first triangle

This will be another long tutorial.

OpenGL 3 makes it easy to write complicated stuff, but at the expense that drawing a simple triangle is actually quite difficult.

Don’t forget to cut’n paste the code on a regular basis.

The first vertex is (-1,-1,0). This means that unless we transform it in some way, it will be displayed at (-1,-1) on the screen. What does this mean ? The screen origin is in the middle, X is on the right, as usual, and Y is up. This is what it gives on a wide screen :

/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// OpenGL ES 2.0 code

#include <jni.h>
#include <android/log.h>

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define  LOG_TAG    "libgl2jni"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

static void printGLString(const char *name, GLenum s) {
    const char *v = (const char *) glGetString(s);
    LOGI("GL %s = %s\n", name, v);
}

static void checkGlError(const char* op) {
    for (GLint error = glGetError(); error; error
            = glGetError()) {
        LOGI("after %s() glError (0x%x)\n", op, error);
    }
}
int texPixel_w,texPixel_h;
bool bAlpha;
GLubyte* texPixels;
GLuint gvNormalHandle;
GLuint gvTexCoordHandle;
GLuint gvSamplerHandle;
GLuint textureID;




static void load_file(){

//	FILE* file = fopen("/sdcard/tex.txt","r");
	FILE* file = fopen("/storage/sdcard0/DCIM/a1.rgb","r");
	int w=480;
	int h=360;
	char *s;
	if (file != NULL)
	{
	  //  fscanf(file,"%d %d",&w,&h);
	    LOGI("w=%d h=%d\n", w, h);
	    texPixel_w=w;
	    texPixel_h=h;
	  //  fscanf(file,"%s",s);
	  //  if(s=="RGB")
	  //  {
	        bAlpha=false;
	        texPixels=new GLubyte[w*h*3];
	        for(int i=0;i<w*h*3;++i)
	        {
	            int a;
	            fscanf(file,"%d",&a);
	            texPixels[i]=(GLubyte)a;
	        }
	        /*
	    }
	    else
	    {
	        bAlpha=true;
	        texPixels=new GLubyte[w*h*4];
	        for(int i=0;i<w*h*4;++i)
	        {
	            int a;
	            fscanf(file,"%d",&a);
	            texPixels[i]=(GLubyte)a;
	        }
	    }*/

	}
}
/*
static const char gVertexShader[] = 
    "attribute vec4 vPosition;\n"
    "void main() {\n"
    "  gl_Position = vPosition;\n"
    "}\n";

static const char gFragmentShader[] = 
    "precision mediump float;\n"
    "void main() {\n"
    "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
    "}\n";
    */
static const char gVertexShader[] = "attribute vec4 a_position;   \n"
                "attribute vec3 a_normal;     \n"
        "attribute vec2 a_texCoord;   \n"
        "varying vec2 v_texCoord;     \n"
        "varying vec3 v_normal; \n"
        "void main()                  \n"
        "{                            \n"
        "   gl_Position = a_position; \n"
        " v_normal = a_normal; \n"
        "   v_texCoord = a_texCoord;  \n"
        "}                            \n";

static const char gFragmentShader[] =
                "precision mediump float;                            \n"
                        "varying vec2 v_texCoord;                            \n"
                        "varying vec3 v_normal; \n"
                        "uniform sampler2D s_texture;                        \n"
                        "void main()                                         \n"
                        "{                                                   \n"
                        "  gl_FragColor = texture2D( s_texture, v_texCoord );\n"
                        "}   \n";
GLuint loadShader(GLenum shaderType, const char* pSource) {
    GLuint shader = glCreateShader(shaderType);
    if (shader) {
        glShaderSource(shader, 1, &pSource, NULL);
        glCompileShader(shader);
        GLint compiled = 0;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
        if (!compiled) {
            GLint infoLen = 0;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen) {
                char* buf = (char*) malloc(infoLen);
                if (buf) {
                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
                    LOGE("Could not compile shader %d:\n%s\n",
                            shaderType, buf);
                    free(buf);
                }
                glDeleteShader(shader);
                shader = 0;
            }
        }
    }
    return shader;
}

GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
    if (!vertexShader) {
        return 0;
    }

    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
    if (!pixelShader) {
        return 0;
    }

    GLuint program = glCreateProgram();
    if (program) {
        glAttachShader(program, vertexShader);
        checkGlError("glAttachShader");
        glAttachShader(program, pixelShader);
        checkGlError("glAttachShader");
        glLinkProgram(program);
        GLint linkStatus = GL_FALSE;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
        if (linkStatus != GL_TRUE) {
            GLint bufLength = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
            if (bufLength) {
                char* buf = (char*) malloc(bufLength);
                if (buf) {
                    glGetProgramInfoLog(program, bufLength, NULL, buf);
                    LOGE("Could not link program:\n%s\n", buf);
                    free(buf);
                }
            }
            glDeleteProgram(program);
            program = 0;
        }
    }

    return program;
}

GLuint gProgram;
GLuint gvPositionHandle;

bool setupGraphics_3(int w, int h) {
    printGLString("Version", GL_VERSION);
    printGLString("Vendor", GL_VENDOR);
    printGLString("Renderer", GL_RENDERER);
    printGLString("Extensions", GL_EXTENSIONS);

    LOGI("setupGraphics(%d, %d)", w, h);
    gProgram = createProgram(gVertexShader, gFragmentShader);
    if (!gProgram) {
        LOGE("Could not create program.");
        return false;
    }
    gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
    checkGlError("glGetAttribLocation");
    LOGI("glGetAttribLocation(\"vPosition\") = %d\n",
            gvPositionHandle);

    glViewport(0, 0, w, h);
    checkGlError("glViewport");
    return true;
}


/////////////////////////////////////////////////////////////
GLuint createSimpleTexture2D(GLuint _textureid, GLubyte* pixels,
                int width, int height, int channels) {

	load_file();


        // Bind the texture
        glActiveTexture(GL_TEXTURE0);
        checkGlError("glActiveTexture");
        // Bind the texture object
        glBindTexture(GL_TEXTURE_2D, _textureid);
        checkGlError("glBindTexture");

        GLenum format;
        switch (channels) {
        case 3:
                format = GL_RGB;
                break;
        case 1:
                format = GL_LUMINANCE;
                break;
        case 4:
                format = GL_RGBA;
                break;
        }
        // Load the texture
        glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format,
                        GL_UNSIGNED_BYTE, pixels);

        checkGlError("glTexImage2D");
        // Set the filtering mode
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

        return _textureid;

}



bool setupGraphics(int w, int h) {
        printGLString("Version", GL_VERSION);
        printGLString("Vendor", GL_VENDOR);
        printGLString("Renderer", GL_RENDERER);
        printGLString("Extensions", GL_EXTENSIONS);

        LOGI("setupGraphics(%d, %d)", w, h);
        gProgram = createProgram(gVertexShader, gFragmentShader);
        if (!gProgram) {
                LOGE("Could not create program.");
                return false;
        }
        gvPositionHandle = glGetAttribLocation(gProgram, "a_position");
        gvNormalHandle=glGetAttribLocation(gProgram,"a_normal");
        gvTexCoordHandle = glGetAttribLocation(gProgram, "a_texCoord");

        gvSamplerHandle = glGetAttribLocation(gProgram, "s_texture");

        // Use tightly packed data
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

        // Generate a texture object
        glGenTextures(1, &textureID);
        if(!bAlpha)
            textureID = createSimpleTexture2D(textureID, texPixels,texPixel_w, texPixel_h, 3);
        else
            textureID = createSimpleTexture2D(textureID, texPixels,texPixel_w, texPixel_h, 3);

        checkGlError("glGetAttribLocation");
        LOGI("glGetAttribLocation(\"vPosition\") = %d\n",
                        gvPositionHandle);

        glViewport(0, 0, w, h);
        checkGlError("glViewport");
        return true;
}
const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
        0.5f, -0.5f };

void renderFrame_square() {

        GLfloat vVertices[] = { -0.75f, 1.0f, 0.0f, // Position 0
                                  0.0f, 1.0f, 0.0f,
                                        0.0f, 0.0f, // TexCoord 0
                        -.75f, -1.0f, 0.0f, // Position 1
                         0.0f,  1.0f, 0.0f,
                         0.0f,  1.0f, // TexCoord 1

                        0.75f, -1.0f, 0.0f, // Position 2
                         0.0f,  1.0f, 0.0f,
                         1.0f,  1.0f, // TexCoord 2

                        0.75f,  1.0f, 0.0f, // Position 3
                        0.0f,   1.0f, 0.0f,
                        1.0f,   0.0f // TexCoord 3
                        };


        GLfloat vVertices_Position[] = { -0.75f, 1.0f, 0.0f, // Position 0
                              -.75f, -1.0f, 0.0f, // Position 1
                              0.75f, -1.0f, 0.0f, // Position 2
                              0.75f,  1.0f, 0.0f, // Position 3
                              };
        GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
        GLsizei stride = 8 * sizeof(GLfloat); // 3 for position, 3 for normal, 2 for texture


        static float grey;
         grey += 0.01f;
         if (grey > 1.0f) {
             grey = 0.0f;
         }
         glClearColor(grey, 1.0f, 1.0f, 1.0f);


        // glClearColor(0.0f, 	0.0f, 1.0f, 1.0f);
        checkGlError("glClearColor");

        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
        checkGlError("glClear");

        glUseProgram(gProgram);
        checkGlError("glUseProgram");

        // Load the vertex position
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride,
                        vVertices);
                        checkGlError("gvPositionHandle");
        glVertexAttribPointer(1,3, GL_FLOAT, GL_FALSE, stride,
                    vVertices+3);
        checkGlError("gvNormalHandle");
        // Load the texture coordinate
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride,
                        vVertices+6);
        checkGlError("gvTexCoordHandle");

        glEnableVertexAttribArray(gvPositionHandle);
        glEnableVertexAttribArray(gvNormalHandle);
     //   glEnableVertexAttribArray(gvTexCoordHandle);


        // Bind the texture
     //   glActiveTexture(GL_TEXTURE0);
    //    glBindTexture(GL_TEXTURE_2D, textureID);

        // Set the sampler texture unit to 0
        glUniform1i(gvSamplerHandle, 0);

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);




   //     glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
   //     checkGlError("glVertexAttribPointer");
   //     glEnableVertexAttribArray(gvPositionHandle);
   //     checkGlError("glEnableVertexAttribArray");
   //     glDrawArrays(GL_TRIANGLES, 0, 3);
   //     checkGlError("glDrawArrays");


}

void renderFrame_square2a(){


}

void renderFrame_3angle() {

    static float grey;
    grey += 0.01f;
    if (grey > 1.0f) {
        grey = 0.0f;
    }
    glClearColor(grey, 1.0f, 1.0f, 1.0f);
    checkGlError("glClearColor");
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    checkGlError("glClear");

    glUseProgram(gProgram);
    checkGlError("glUseProgram");

    glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
    checkGlError("glVertexAttribPointer");
    glEnableVertexAttribArray(gvPositionHandle);
    checkGlError("glEnableVertexAttribArray");
    glDrawArrays(GL_TRIANGLES, 0, 3);
    checkGlError("glDrawArrays");
}
// http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
void renderFrame_square2(){


    glClearColor(0, 1.0f, 1.0f, 1.0f);
    checkGlError("glClearColor");
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    checkGlError("glClear");

    glUseProgram(gProgram);


    ////////
	static const GLfloat g_vertex_buffer_data[] = {
	   -1.0f, -0.5f, 0.0f,
	   1.0f, -0.5f, 0.0f,
	   0.0f,  1.0f, 0.0f,
	};
	/////////////////


	// This will identify our vertex buffer
	GLuint vertexbuffer;

	// Generate 1 buffer, put the resulting identifier in vertexbuffer
	glGenBuffers(1, &vertexbuffer);

	// The following commands will talk about our 'vertexbuffer' buffer
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

	// Give our vertices to OpenGL.
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);


	/////////////////


	// 1rst attribute buffer : vertices
//	glEnableVertexAttribArray(0);
//	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	/*
	glVertexAttribPointer(
	   0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
	   3,                  // size
	   GL_FLOAT,           // type
	   GL_FALSE,           // normalized?
	   0,                  // stride
	   (void*)0            // array buffer offset
	);
*/
	// Draw the triangle !
//
//	glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle

//	glDisableVertexAttribArray(0);



    glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, 0,  (void*)0 );
 //   glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
 //   checkGlError("glVertexAttribPointer");
    glEnableVertexAttribArray(gvPositionHandle);
//    checkGlError("glEnableVertexAttribArray");
    glDrawArrays(GL_TRIANGLES, 0, 3);
//    checkGlError("glDrawArrays");


}
void renderFrame() {
//	renderFrame_3angle();
//	renderFrame_square();
//	renderFrame_2_square
	renderFrame_square2();

}
extern "C" {
    JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj,  jint width, jint height);
    JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj);
};

JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj,  jint width, jint height)
{
    setupGraphics(width, height);
}

JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj)
{
    renderFrame();
}

shareShare on FacebookShare on Google+Share on LinkedInEmail this to someonePrint this pageBuffer this pageDigg thisFlattr the authorShare on RedditPin on PinterestShare on StumbleUponShare on TumblrTweet about this on Twitter

By


Readers Comments (0)


You must be logged in to post a comment.

PowenKo’s Online Store

powenko_arduinoBook
Android7

Amazon

adsbygoogle

Recent Posts

Categories

Amazon