Reputation: 11
reference: how-to-load-and-display-an-image-in-opengl-es-3-0-using-c
#include <jni.h>
#include <android/log.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#include <GLES3/gl3ext.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define STB_IMAGE_IMPLEMENTATION
#include "include/stb_image.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__)
GLuint mTexture, VAO;// Create reference Id for the texture
GLuint gProgram;
GLuint gvPositionHandle;
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);
}
}
auto gVertexShader =
"#version 300 es\n"
"layout (location=0) in vec3 position;\n"
"layout (location=1) in vec3 color;\n"
"layout (location=2) in vec2 texCoord;\n"
"out vec3 ourColor;\n"
"out vec2 TexCoord;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position,1.0f); // Add the xOffset to the x position of the vertex position\n"
"ourColor = color;\n"
"TexCoord= vec2(texCoord.x,1.0f-texCoord.y);\n"
"}";
auto gFragmentShader =
"#version 300 es\n"
"in vec3 ourColor;\n"
"in vec2 TexCoord;\n"
"out vec4 color;\n"
"uniform sampler2D ourTexture;\n"
"void main()\n"
"{\n"
"color = texture(ourTexture , 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) { // Load and Bind Fragments to Progam and link program then return result
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;
}
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, "position");
checkGlError("glGetAttribLocation");
LOGI("glGetAttribLocation(\"position\") = %d\n",
gvPositionHandle);
glViewport(0, 0, w, h);
checkGlError("glViewport");
return true;
}
GLfloat recVertices[] = {
// Positions // Colors // Texture Coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Top Right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // Top Left
};
GLuint indices[] = { // Note that we start from 0!
0, 1, 3, // First Triangle
1, 2, 3 // Second Triangle
};
void initBuffers()
{
GLuint VBOs[2], EBO; // Initialize an buffer to store all the verticles and transfer them to the GPU
glGenVertexArrays (1,&VAO); // Generate VAO
glGenBuffers(1, VBOs); // Generate VBO
glGenBuffers(1, &EBO); // Generate EBO
glBindVertexArray (VAO);// Bind the Vertex Array
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);//Bind verticles array for OpenGL to use
glBufferData(GL_ARRAY_BUFFER, sizeof(recVertices), recVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//Bind the indices for information about drawing sequence
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 1. set the vertex attributes pointers
// Position Attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color Attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
//Texture Coordinate Attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindVertexArray(0);//3. Unbind VAO
}
void generateTexture()
{
glGenTextures(1 , &mTexture);
glBindTexture(GL_TEXTURE_2D, mTexture);// Bind our 2D texture so that following set up will be applied
//Set texture wrapping parameter
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_MIRRORED_REPEAT);
//Set texture Filtering parameter
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
int picWidth,picHeight,n;
unsigned char* image = stbi_load("/storage/emulated/0/Pictures/frame.png", &picWidth, &picHeight, &n,0);
if (image == NULL ) {
LOGI("Failed to load image: %s", stbi_failure_reason());
}
//Generate the image
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA , picWidth , picHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(image);// Free the reference to the image
glBindTexture(GL_TEXTURE_2D,0); //Unbind 2D textures
}
void renderFrame() {
static float grey;
grey += 0.01f;
if (grey > 1.0f) {
grey = 0.0f;
}
generateTexture();
glClearColor(grey+0.05f, grey-0.03f, grey+0.02f, grey-0.04f);
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, recVertices);
checkGlError("glVertexAttribPointer");
glEnableVertexAttribArray(gvPositionHandle);
checkGlError("glEnableVertexAttribArray");
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
checkGlError("glDrawArrays");*/
glActiveTexture(GL_TEXTURE0);
checkGlError("glActiveTexture");
glBindTexture(GL_TEXTURE_2D,mTexture);
checkGlError("glBindTexture");
GLint mlocation = glGetUniformLocation(gProgram,"ourTexture");
checkGlError("glGetUniformLocation");
glUniform1i(mlocation,0);
checkGlError("glUniform1i");
initBuffers();
glBindVertexArray(VAO);
checkGlError("glBindVertexArray");
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
}
extern "C" {
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv *env, jobject assetManager,
jint width,
jint height);
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv *env, jobject assetManager);
};
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv* env, jobject assetManager,
jint width,
jint height) {
setupGraphics(width, height);
}
JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv* env,jobject assetManager) {
renderFrame();
}
I am using this following code in my sample Android NDK app using OpenGL-ES 3.0 and stb_image library. But I am getting error while accessing an image with following in api call stb_load(). even I have added android permissions in xml file.
Android log I am getting:
533986 10-03 15:43:53.528 E 4714 26053 MediaProvider: Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
533988 10-03 15:43:53.537 E 4714 5104 MediaProvider: Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
533990 10-03 15:43:53.544 E 4714 5109 MediaProvider: Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
533992 10-03 15:43:53.553 E 4714 26457 MediaProvider: Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
533994 10-03 15:43:53.562 E 4714 8229 MediaProvider: Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
533996 10-03 15:43:53.570 E 4714 14229 MediaProvider: Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
533998 10-03 15:43:53.578 E 4714 26053 MediaProvider: Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
534000 10-03 15:43:53.586 E 4714 5104 MediaProvider: Permission to access file: /storage/emulated/0/Pictures/frame.png is denied
I tried using giving android permissions:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:required="true"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:required="true"/>
And using stb_load.h library to load the image.
Upvotes: 1
Views: 48