1. 程式人生 > >一個簡單的OpenGL ES 3.0 示例 (Android NDK jni)

一個簡單的OpenGL ES 3.0 示例 (Android NDK jni)

OpenGL ES 3.0 上的一個三角形例子,網上可以下載到android skd 版(java)和 android ndk (c&c++版)

為了瞭解一下JNI,於是寫了如下小程式。

這個例子是使用jni, java中呼叫c中的程式碼完成三角形的渲染, 其中shader程式碼儲存在assets目錄下,如下目錄圖:


其中,com_jnirenderer_RendererJNI.h 是 使用javah命令生成的,進入bin/classes目錄下執行如下命令:

javah -classpath "D:\Program Files (x86)\Android\android-sdk\platforms\android-20\android.jar";. -jni PackageName.ClassName  (注意路徑、包名以及類名的替換)

MainActivity.java程式碼如下:

package com.jnirenderer;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity {

	private final int CONTEXT_CLIENT_VERSION = 3;
	private GLSurfaceView mGLSurfaceView;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		mGLSurfaceView = new GLSurfaceView(this);
		if (detectOpenGLES30()) {
			mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
			mGLSurfaceView.setRenderer(new RendererJNI(this));
		} else {
			Log.e("opengles30", "OpenGL ES 3.0 not supported on device.  Exiting...");
			finish();
		}
		
		setContentView(mGLSurfaceView);
	}
	
	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		mGLSurfaceView.onResume();
	}
	
	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		mGLSurfaceView.onPause();
	}
	
	private boolean detectOpenGLES30() {
		ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
		ConfigurationInfo info = am.getDeviceConfigurationInfo();
		
		return (info.reqGlEsVersion >= 0x30000);
	}
}

RendererJNI.java程式碼如下:
package com.jnirenderer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.content.res.AssetManager;
import android.opengl.GLSurfaceView;
import android.util.Log;

public class RendererJNI implements GLSurfaceView.Renderer {

	static {
		System.loadLibrary("JNIOpenGLES30");
	}
	
	private AssetManager mAssetMgr = null;
	private final String mLogTag = "ndk-build";
	
	public native void glesInit();
	public native void glesRender();
	public native void glesResize(int width, int height);
	
	public native void readShaderFile(AssetManager assetMgr);
	
	public RendererJNI(Context context) {
		mAssetMgr = context.getAssets();
		if (null == mAssetMgr) {
			Log.e(mLogTag, "getAssets() return null !");
		}
	}
	
	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		// TODO Auto-generated method stub
		readShaderFile(mAssetMgr);
		glesInit();
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		// TODO Auto-generated method stub
		glesResize(width, height);
	}

	@Override
	public void onDrawFrame(GL10 gl) {
		// TODO Auto-generated method stub
		glesRender();
	}
}

com_jnirenderer_RendererJNI.c 程式碼如下:
#include "com_jnirenderer_RendererJNI.h"
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <GLES3/gl3.h>
#include <android/asset_manager_jni.h>
#include <android/log.h>


#define LOG_TAG "ndk-build"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

GLint	g_programObject;
jint	g_width;
jint	g_height;

AAssetManager* g_pAssetManager = NULL;

char* readShaderSrcFile(char *shaderFile, AAssetManager *pAssetManager)
{
	AAsset *pAsset = NULL;
	char *pBuffer = NULL;
	off_t size = -1;
	int numByte = -1;

	if (NULL == pAssetManager)
	{
		LOGE("pAssetManager is null!");
		return NULL;
	}
	pAsset = AAssetManager_open(pAssetManager, shaderFile, AASSET_MODE_UNKNOWN);
	//LOGI("after AAssetManager_open");

	size = AAsset_getLength(pAsset);
	LOGI("after AAssetManager_open");
	pBuffer = (char *)malloc(size+1);
	pBuffer[size] = '\0';

	numByte = AAsset_read(pAsset, pBuffer, size);
	LOGI("%s : [%s]", shaderFile, pBuffer);
	AAsset_close(pAsset);

	return pBuffer;
}


GLuint LoadShader ( GLenum type, const char *shaderSrc )
{
   GLuint shader;
   GLint compiled;

   // Create the shader object
   shader = glCreateShader ( type );

   if ( shader == 0 )
   {
      return 0;
   }

   // Load the shader source
   glShaderSource ( shader, 1, &shaderSrc, NULL );

   // Compile the shader
   glCompileShader ( shader );

   // Check the compile status
   glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );

   if ( !compiled )
   {
      GLint infoLen = 0;

      glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );

      if ( infoLen > 1 )
      {
         char *infoLog = malloc ( sizeof ( char ) * infoLen );

         glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
         LOGE("Error compiling shader:[%s]", infoLog );

         free ( infoLog );
      }

      glDeleteShader ( shader );
      return 0;
   }

   return shader;

}

//*********************************************************************************
//
JNIEXPORT void JNICALL Java_com_jnirenderer_RendererJNI_readShaderFile(JNIEnv *env, jobject self, jobject assetManager)
{
	 if (assetManager && env)
	 {
		 //LOGI("before AAssetManager_fromJava");
		 g_pAssetManager = AAssetManager_fromJava(env, assetManager);
		 //LOGI("after AAssetManager_fromJava");
		 if (NULL == g_pAssetManager)
		 {
			 LOGE("AAssetManager_fromJava() return null !");
		 }
	 }
	 else
	 {
		 LOGE("assetManager is null !");
	 }
}

//*********************************************************************************
//
JNIEXPORT void JNICALL Java_com_jnirenderer_RendererJNI_glesInit(JNIEnv *pEnv, jobject obj)
{
	   char vShaderStr[] =
	      "#version 300 es                          \n"
	      "layout(location = 0) in vec4 vPosition;  \n"
	      "void main()                              \n"
	      "{                                        \n"
	      "   gl_Position = vPosition;              \n"
	      "}                                        \n";

	   char fShaderStr[] =
	      "#version 300 es                              \n"
	      "precision mediump float;                     \n"
	      "out vec4 fragColor;                          \n"
	      "void main()                                  \n"
	      "{                                            \n"
	      "   fragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );  \n"
	      "}                                            \n";

	   char *pVertexShader = readShaderSrcFile("shader/vs.glsl", g_pAssetManager);
	   char *pFragmentShader = readShaderSrcFile("shader/fs.glsl", g_pAssetManager);

	   GLuint vertexShader;
	   GLuint fragmentShader;
	   GLuint programObject;
	   GLint linked;

	   // Load the vertex/fragment shaders
	   //vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
	   //fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );
	   vertexShader = LoadShader ( GL_VERTEX_SHADER, pVertexShader );
	   fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, pFragmentShader );

	   // Create the program object
	   programObject = glCreateProgram ( );

	   if ( programObject == 0 )
	   {
	      return;
	   }

	   glAttachShader ( programObject, vertexShader );
	   glAttachShader ( programObject, fragmentShader );

	   // Link the program
	   glLinkProgram ( programObject );

	   // Check the link status
	   glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );

	   if ( !linked )
	   {
	      GLint infoLen = 0;

	      glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );

	      if ( infoLen > 1 )
	      {
	         char *infoLog = malloc ( sizeof ( char ) * infoLen );

	         glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
	         LOGE("Error linking program:[%s]", infoLog );

	         free ( infoLog );
	      }

	      glDeleteProgram ( programObject );
	      return;
	   }

	   // Store the program object
	   g_programObject = programObject;

	   glClearColor ( 1.0f, 1.0f, 1.0f, 0.0f );

}

//*********************************************************************************
//
JNIEXPORT void JNICALL Java_com_jnirenderer_RendererJNI_glesRender(JNIEnv *pEnv, jobject obj)
{
	   GLfloat vVertices[] = {  0.0f,  0.5f, 0.0f,
	                            -0.5f, -0.5f, 0.0f,
	                            0.5f, -0.5f, 0.0f
	                         };

	   // Set the viewport
	   glViewport ( 0, 0, g_width, g_height );

	   // Clear the color buffer
	   glClear ( GL_COLOR_BUFFER_BIT );

	   // Use the program object
	   glUseProgram ( g_programObject );

	   // Load the vertex data
	   glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
	   glEnableVertexAttribArray ( 0 );

	   glDrawArrays ( GL_TRIANGLES, 0, 3 );
}

//*********************************************************************************
//
JNIEXPORT void JNICALL Java_com_jnirenderer_RendererJNI_glesResize(JNIEnv *pEnv, jobject obj, jint width, jint height)
{
	g_width = width;
	g_height = height;
}

vs.glsl 和 fs.glsl 中的shader程式碼分別如下:
#version 300 es

layout(location = 0) in vec4 vPosition;

void main()
{
	gl_Position = vPosition;
}
#version 300 es

precision mediump float;
out vec4 fragColor;

void main()
{
	fragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

Android.mk 如下:
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := JNIOpenGLES30

LOCAL_SRC_FILES := com_jnirenderer_RendererJNI.c

LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv3

include $(BUILD_SHARED_LIBRARY)

程式執行的效果和書上給的完全一樣,一個紅三角形 ! ! !

相關推薦

一個簡單OpenGL ES 3.0 示例 Android NDK jni

OpenGL ES 3.0 上的一個三角形例子,網上可以下載到android skd 版(java)和 android ndk (c&c++版) 為了瞭解一下JNI,於是寫了如下小程式。 這個例子是使用jni, java中呼叫c中的程式碼完成三角形的渲染, 其中sh

android studio | openGL es 3.0增強現實AR開發 (1) 建立一個openGL es 3.0開發環境

1.什麼是NDK,什麼是JNI? NDK:Native Development Kit(原生開發工具包), NDK允許使用者使用類似C / C++之類的原生程式碼語言執行部分程式。它包括下面的部分(1)從C / C++生成原生程式碼庫所需要的工具和buil

Android 為例編寫一個 OpenGL ES 3.0 例項,Native & Java 兩種實現

一、簡介 通過這個 Sample,你將瞭解到 Android 中是怎麼使用 OpenGL ES 通過繪製一個簡單的靜態三角形,來簡單入門和了解它大致的流程(類似於 HelloWorld 工程) 介紹使用 Native 層 和 Java 層 兩種方式來分別實現

通俗易懂的 OpenGL ES 3.0渲染三角形

前言 學習了OpenGL有一段時間,在繪製出屬於自己的三角形之前,會接觸許多理論上的知識。用簡單的方式寫下自己對OpenGL的一些見解。望大家取其精華去其糟粕 最終效果:改變背景色,並且繪製渲染一個暗紅色的三角形 必備知識 OpenGL需要我們至少設定一個

OpenGL ES 3.0 簡單的頂點和片段著色器

char fShaderStr[] = 1、 "#version 300 es \n" 2、 "precision mediump float; \n" 3、 "out vec4 fragColor;

通俗易懂的 OpenGL ES 3.0入門必備知識!!

前言 opengl的入門是個難點,因為在繪製出圖形之前,你必須要學習一大堆的概念,以及部分圖形知識。以至於在程式碼中不迷路-v-!!.接下來就通俗的講解下部分概念知識。希望大家取其精華去其糟粕 頂點(Vertex)      opengl物體圖形都由點、線

iOS下OpenGL ES 3.0程式設計入門:構建Hello World環境

OpenGL ES簡介:      OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL三維圖形 API 的子集,針對手機、PDA和遊戲主機等嵌入式裝置而設計。該API由Khronos集團定義推廣,Khronos是一個圖形軟硬體

android平臺下OpenGL ES 3.0從零開始

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

android平臺下OpenGL ES 3.0繪製純色背景

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

android平臺下OpenGL ES 3.0從矩形中看矩陣和座標系

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

android平臺下OpenGL ES 3.0繪製彩色三角形

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

android平臺下OpenGL ES 3.0繪製圓點、直線和三角形

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

android平臺下OpenGL ES 3.0著色語言基礎知識(下)

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

android平臺下OpenGL ES 3.0例項詳解頂點屬性、頂點陣列

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

android平臺下OpenGL ES 3.0例項詳解頂點緩衝區物件(VBO)和頂點陣列物件(VAO)

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

android平臺下OpenGL ES 3.0繪製立方體的幾種方式

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

android平臺下OpenGL ES 3.0使用GLSurfaceView對相機Camera預覽實時處理

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

android平臺下OpenGL ES 3.0使用TextureView對相機Camera預覽實時處理

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

android平臺下OpenGL ES 3.0實現2D紋理貼圖顯示bitmap

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

OpenGL ES 3.0 渲染管線介紹

一、前言 OpenGL 1.x 系列採用的還是固定功能管線。 從 OpenGL ES 2.0 開始採用了可程式設計圖形管線。 而 OpenGL ES 3.0 相容了 2.0,並加入了很多 2.0 不具備的功能。 Android 4.3 之後開始支援 Open