国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【OpenGL ES】三維圖形繪制

這篇具有很好參考價(jià)值的文章主要介紹了【OpenGL ES】三維圖形繪制。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。


不積跬步,無以至千里;不積小流,無以成江海。要沉下心來,詩和遠(yuǎn)方的路費(fèi)真的很貴!

OpenGL ES 學(xué)習(xí)——3D

顏色的簡單搭配:

不紅+不綠+不藍(lán) = 黑

紅+綠+藍(lán) = 白

紅+綠 = 黃

紅+藍(lán) = 紫

綠+藍(lán) = 青藍(lán)

投影矩陣

投影主要分為正交投影透視投影兩種。

正交投影

沒有近大遠(yuǎn)小的效果,是平行投影,投影顯示的大小就是物體的大小。

Matrix.orthoM方法
  • 這是在Java中設(shè)置正交投影的函數(shù)。
Matrix.orthoM(mProjectMatrix, 0, left, right, bottom, top, near, far);

【OpenGL ES】三維圖形繪制

glm::ortho方法
  • C++語言中,沒有專門的數(shù)學(xué)庫來處理矩陣,所以我們需要自己引入第三方庫GLM。
  • 在官網(wǎng)下載GLM庫,然后解壓,將glm文件夾加入到C++下面的include文件夾中,然后在文件中書寫頭文件即可使用。
template<typename T>
	GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> ortho(T left, T right, T bottom, T top, T zNear, T zFar)
	{
		if(GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_ZO)
			return orthoLH_ZO(left, right, bottom, top, zNear, zFar);
		else if(GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_NO)
			return orthoLH_NO(left, right, bottom, top, zNear, zFar);
		else if(GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO)
			return orthoRH_ZO(left, right, bottom, top, zNear, zFar);
		else if(GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_NO)
			return orthoRH_NO(left, right, bottom, top, zNear, zFar);
	}
  • 還是和Java中方法相似,就是無偏移量參數(shù),數(shù)據(jù)保存在矩陣中了,無需再一個(gè)內(nèi)存來保存數(shù)據(jù)了。

透視投影

特點(diǎn)是近大遠(yuǎn)小,模擬人的眼球,近的物體顯示大,遠(yuǎn)的物體顯示小,發(fā)散光。

相機(jī)位置

相機(jī)位置,就是所謂的人所在位置,即觀察者所在的位置。

Javac++中都有函數(shù)來設(shè)置相機(jī)位置,來觀察物體。通過

改變相機(jī)位置,可以使我們觀察到物體的每一個(gè)位置。

Matrix.setLookAtM方法

  • 這是在Java中設(shè)置相機(jī)位置的函數(shù)。
Matrix.setLookAtM(
    mVMatrix,0,  
    cx,cy,cz,   //相機(jī)位置
    tx,ty,tz,   //目標(biāo)點(diǎn)坐標(biāo)
    upx,upy,upz);  //視點(diǎn)位置,即眼睛位置
  • 第二個(gè)參數(shù)是偏移量,大多數(shù)情況都默認(rèn)為0。
  • 最后將這些數(shù)據(jù)都存入mVMatrix中。

glm::lookAt方法

template<typename T, qualifier Q>
	GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAt(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up)
	{
		GLM_IF_CONSTEXPR(GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT)
			return lookAtLH(eye, center, up);
		else
			return lookAtRH(eye, center, up);
	}
  • 返回一個(gè)mat4的矩陣。
  • 參數(shù)就是三個(gè)vec3的向量:第一個(gè)就是相機(jī)位置,第二個(gè)就是目標(biāo)點(diǎn)坐標(biāo),第三個(gè)是視點(diǎn)位置。

變換

我們熟知的變換方式有平移,旋轉(zhuǎn),縮放

平移

旋轉(zhuǎn)

縮放

多個(gè)彩色三角形利用相機(jī)和矩陣形成立體效果

繪制立方體

對(duì)于三維圖形來說,相機(jī)的朝向和角度是關(guān)鍵,看的視角很關(guān)鍵,不然你繪制是個(gè)立體圖形,但是只能看到一個(gè)平面。

  • 頂點(diǎn)著色器
#version 300 es
in vec4 vPosition;
in vec4 vColor;
uniform mat4 vMatrix;
out vec4 aColor;
void main() {
     gl_Position  = vMatrix*vPosition;
     gl_PointSize = 10.0;
     aColor = vColor;
}
  • 片元著色器
#version 300 es
precision mediump float;
in vec4 aColor;
out vec4 fragColor;
void main() {
     fragColor = aColor;
}

JAVA版本

  • Renderer類
package com.example.openglndk;

import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

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

//渲染器,把3D物體繪制到屏幕上
public class MyRenderer implements GLSurfaceView.Renderer {
    //坐標(biāo)系xyz
    private final static int COORDS_PER_VERTEX = 3;
    //顏色通道(RGBA)
    private final static int COORDS_PER_COLOR = 4;
    //頂點(diǎn)之間的偏移量
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)
    //顏色之間的偏移量
    private final int colorStride = COORDS_PER_COLOR * 4; // 每個(gè)顏色四個(gè)字節(jié)
    //聲明內(nèi)存分配的數(shù)據(jù)類型
    private FloatBuffer vertexBuffer, colorBuffer;
    private ShortBuffer indexBuffer;
    //著色器和管理程序
    private int vertexShader;
    private int fragmentShader;
    private int mProgram;
    //彩色數(shù)據(jù)
    private float colors[] = {
            0f,1f,1f,1f,
            1f,1f,0f,1f,
            1f,0f,1f,1f,
            0f,1f,0f,1f,
            1f,0f,0f,1f,
            0f,0f,1f,1f,
            1f,1f,1f,1f,
            0f,0f,0f,1f,
    };

    //定義點(diǎn)坐標(biāo)
    private float vertexPoints[] = {
            0.5f, 0.5f, 0.5f,  //右面左上0
            0.5f, 0.5f, -0.5f, //右面左下1
            -0.5f, 0.5f, 0.5f, //右面右上2
            -0.5f, 0.5f, -0.5f, //右面右下3

            0.5f, -0.5f, 0.5f,  //左面右上4
            0.5f, -0.5f, -0.5f, //左面右下5
            -0.5f, -0.5f, 0.5f, //左面左上6
            -0.5f, -0.5f, -0.5f, //左面左下7
    };

    //索引
    private short index[] = {
            //上
            0, 1, 2,
            1, 2, 3,
            //下
            4, 5, 6,
            5, 6, 7,
            //左
            2, 3, 6,
            3, 6, 7,
            //右
            0, 1, 4,
            1, 4, 5,
            //前
            0, 2, 4,
            2, 4, 6,
            //后
            1, 3, 7,
            1, 7, 5

    };

    //點(diǎn)數(shù)量
    private int vertexCount = vertexPoints.length / COORDS_PER_VERTEX;

    //頂點(diǎn)著色器代碼
    private String vertexShaderCode = "#version 300 es\n" +
            "in vec4 vPosition;\n" +
            "in vec4 vColor;\n" +
            "uniform mat4 vMatrix;\n" +
            "out vec4 aColor;\n" +
            "void main() {\n" +
            "     gl_Position  = vMatrix*vPosition;\n" +
            "     gl_PointSize = 10.0;\n" +
            "     aColor = vColor;\n" +
            "}\n";

    //片元著色器代碼
    private String fragmentShaderCode = "#version 300 es\n" +
            "precision mediump float;\n" +
            "in vec4 aColor;\n" +
            "out vec4 fragColor;\n" +
            "void main() {\n" +
            "     fragColor = aColor;\n" +
            "}\n";


    //構(gòu)造函數(shù)
    public MyRenderer() {
        //分配頂點(diǎn)內(nèi)存
        vertexBuffer = ByteBuffer.allocateDirect(vertexPoints.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        //傳入指定的坐標(biāo)數(shù)據(jù)
        //將語法推送給GPU
        vertexBuffer.put(vertexPoints);
        vertexBuffer.position(0);
        //分配顏色內(nèi)存
        colorBuffer = ByteBuffer.allocateDirect(colors.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        //傳入指定的數(shù)據(jù)
        colorBuffer.put(colors);
        colorBuffer.position(0);
        //索引
        indexBuffer = ByteBuffer.allocateDirect(index.length * 2)
                .order(ByteOrder.nativeOrder())
                .asShortBuffer();
        indexBuffer.put(index);
        indexBuffer.position(0);
    }

    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
        //設(shè)置背景顏色為白色
        GLES30.glClearColor(1, 1, 1, 1);
        //創(chuàng)建頂點(diǎn)著色器
        vertexShader = LoadShader(GLES30.GL_VERTEX_SHADER, vertexShaderCode);
        //創(chuàng)建片元著色器
        fragmentShader = LoadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode);
        //將頂點(diǎn)著色器和片元著色器交給統(tǒng)一程序管理
        mProgram = linkProgram(vertexShader, fragmentShader);
    }

    /**
     * 圖形尺寸
     *
     * @param gl10
     * @param width
     * @param height
     */
    private float mProjectionMatrix[] = new float[16];
    private float mViewMatrix[] = new float[16];
    private float mMVPMatrix[] = new float[16];

    @Override
    public void onSurfaceChanged(GL10 gl10, int width, int height) {
        //設(shè)置視口
        GLES30.glViewport(0, 0, width, height);
        //寬高比
        float ratio = (float) width / height;
        //正交投影只能看見一個(gè)面
        //設(shè)置透視投影矩陣
        Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
        //設(shè)置相機(jī)角度(核心)
        Matrix.setLookAtM(mViewMatrix, 0, 3, 3, 3, 0f, 0f, 0f, 1f, 0f, 1.0f);
        //矩陣合并
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
    }

    /**
     * @param gl10 渲染
     */
    @Override
    public void onDrawFrame(GL10 gl10) {
        //清除顏色緩沖區(qū)和深度緩沖區(qū)
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);
        //開啟深度測(cè)試
        GLES30.glEnable(GLES30.GL_DEPTH_TEST);
        //使用統(tǒng)一的管理程序
        GLES30.glUseProgram(mProgram);
        //獲取變換矩陣vMatrix成員句柄
        //圖形參數(shù)
        int mMatrixHandler = GLES30.glGetUniformLocation(mProgram, "vMatrix");
        //指定vMatrix的值
        GLES30.glUniformMatrix4fv(mMatrixHandler, 1, false, mMVPMatrix, 0);
        //獲取頂點(diǎn)著色器的vPosition成員句柄
        int mPositionHandle = GLES30.glGetAttribLocation(mProgram, "vPosition");
        //啟用頂點(diǎn)的句柄
        GLES30.glEnableVertexAttribArray(mPositionHandle);
        //準(zhǔn)備坐標(biāo)數(shù)據(jù)
        GLES30.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                GLES30.GL_FLOAT, false,
                vertexStride, vertexBuffer);
        //獲取片元著色器的vColor成員的句柄
        //因?yàn)槭遣噬瑪?shù)據(jù)類型和頂點(diǎn)類似,所以必須是glGetAttribLocation方法
        //glGetUniformLocation方法畫不全顏色,會(huì)變成黑色
        int mColorHandle = GLES30.glGetAttribLocation(mProgram, "vColor");
        //啟動(dòng)顏色的句柄
        GLES30.glEnableVertexAttribArray(mColorHandle);
        //設(shè)置圖形的顏色
        //準(zhǔn)備顏色數(shù)據(jù)
        GLES30.glVertexAttribPointer(mColorHandle, COORDS_PER_COLOR,
                GLES30.GL_FLOAT, false,
                colorStride, colorBuffer);
//        GLES30.glUniform4fv(mColorHandle, 1, colors, 0);
        //繪制圖形
        GLES30.glLineWidth(10.0f);
//        GLES30.glDrawArrays(GLES30.GL_LINE_LOOP, 0, vertexCount);
        //索引法繪制圖形,索引繪制三角形,無需在用扇形,直接繪制即可
        GLES30.glDrawElements(GLES30.GL_TRIANGLES, index.length,
                GLES30.GL_UNSIGNED_SHORT, indexBuffer);
        //禁止顏色數(shù)組的句柄
        GLES30.glDisableVertexAttribArray(mColorHandle);
        //禁止頂點(diǎn)數(shù)組的句柄
        GLES30.glDisableVertexAttribArray(mPositionHandle);
    }


    /**
     * 編譯
     *
     * @param type       頂點(diǎn)著色器:GLES30.GL_VERTEX_SHADER
     *                   片段著色器:GLES30.GL_FRAGMENT_SHADER
     * @param shaderCode
     * @return
     */
    private static int LoadShader(int type, String shaderCode) {
        //創(chuàng)建一個(gè)著色器
        final int shaderId = GLES30.glCreateShader(type);
        if (shaderId != 0) {
            //加載到著色器
            GLES30.glShaderSource(shaderId, shaderCode);
            //編譯著色器
            GLES30.glCompileShader(shaderId);
            //檢測(cè)狀態(tài)
            final int[] compileStatus = new int[1];
            GLES30.glGetShaderiv(shaderId, GLES30.GL_COMPILE_STATUS, compileStatus, 0);
            if (compileStatus[0] == 0) {
                String logInfo = GLES30.glGetShaderInfoLog(shaderId);
                System.err.println(logInfo);
                //創(chuàng)建失敗
                GLES30.glDeleteShader(shaderId);
                return 0;
            }
            return shaderId;
        } else {
            //創(chuàng)建失敗
            return 0;
        }
    }

    /**
     * 鏈接小程序
     *
     * @param vertexShaderId   頂點(diǎn)著色器
     * @param fragmentShaderId 片段著色器
     * @return
     */
    public static int linkProgram(int vertexShaderId, int fragmentShaderId) {
        final int programId = GLES30.glCreateProgram();
        if (programId != 0) {
            //將頂點(diǎn)著色器加入到程序
            GLES30.glAttachShader(programId, vertexShaderId);
            //將片元著色器加入到程序中
            GLES30.glAttachShader(programId, fragmentShaderId);
            //鏈接著色器程序
            GLES30.glLinkProgram(programId);
            final int[] linkStatus = new int[1];
            GLES30.glGetProgramiv(programId, GLES30.GL_LINK_STATUS, linkStatus, 0);
            if (linkStatus[0] == 0) {
                String logInfo = GLES30.glGetProgramInfoLog(programId);
                System.err.println(logInfo);
                GLES30.glDeleteProgram(programId);
                return 0;
            }
            return programId;
        } else {
            //創(chuàng)建失敗
            return 0;
        }
    }
}

C++版本

  • .cpp文件
//
// Created by lvjunkai on 2022/2/21.
//
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <jni.h>
#include <malloc.h>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/glm.hpp>

//聲明自定義函數(shù)
//創(chuàng)建編譯加載
GLuint LoadShader(int type, char *shaderCode);

//鏈接統(tǒng)一程序
GLuint linkProgram(GLuint vertexShader, GLuint fragmentShader);

//模板技術(shù)定義的函數(shù)
//用于求數(shù)組長度
template<class T>
GLsizei getArrayLen(T &array) {
    return (sizeof(array) / sizeof(array[0]));
}


//坐標(biāo)個(gè)數(shù)(xyz)
const GLint COORDS_PER_VERTEX = 3;

const GLint COORDS_PER_COLOR = 4;

//頂點(diǎn)之間的偏移量
const GLsizei vertexStride = COORDS_PER_VERTEX * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)
//顏色之間的偏移量
const GLsizei colorStride = COORDS_PER_COLOR * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)

//聲明頂點(diǎn)著色器
GLuint vertexShader;
//聲明片元著色器
GLuint fragmentShader;
//聲明著色器管理程序
GLuint mProgram;
//顏色
float colors[] = {
        0.0f,1.0f,1.0f,1.0f,
        1.0f,1.0f,0.0f,1.0f,
        1.0f,0.0f,1.0f,1.0f,
        0.0f,1.0f,0.0f,1.0f,
        1.0f,0.0f,0.0f,1.0f,
        0.0f,0.0f,1.0f,1.0f,
        1.0f,1.0f,1.0f,1.0f,
        0.0f,0.0f,0.0f,1.0f,
};


//定義點(diǎn)坐標(biāo)
float vertexPoints[] = {
        0.5f, 0.5f, 0.5f,  //右面左上0
        0.5f, 0.5f, -0.5f, //右面左下1
        -0.5f, 0.5f, 0.5f, //右面右上2
        -0.5f, 0.5f, -0.5f, //右面右下3

        0.5f, -0.5f, 0.5f,  //左面右上4
        0.5f, -0.5f, -0.5f, //左面右下5
        -0.5f, -0.5f, 0.5f, //左面左上6
        -0.5f, -0.5f, -0.5f, //左面左下7
};

//索引
short index[] = {
        //上
        0, 1, 2,
        1, 2, 3,
        //下
        4, 5, 6,
        5, 6, 7,
        //左
        2, 3, 6,
        3, 6, 7,
        //右
        0, 1, 4,
        1, 4, 5,
        //前
        0, 2, 4,
        2, 4, 6,
        //后
        1, 3, 7,
        1, 7, 5

};


//頂點(diǎn)個(gè)數(shù)
GLsizei vertexCount = getArrayLen(vertexPoints) / COORDS_PER_VERTEX;

//頂點(diǎn)著色器代碼
char vertexShaderCode[] = "#version 300 es\n"
                          "in vec4 vPosition;\n"
                          "in vec4 vColor;\n"
                          "uniform mat4 vMatrix;\n"
                          "out vec4 aColor;\n"
                          "void main() {\n"
                          "     gl_Position  = vMatrix*vPosition;\n"
                          "     gl_PointSize = 10.0;\n"
                          "     aColor = vColor;\n"
                          "}";

//片段著色器代碼
char fragmentShaderCode[] = "#version 300 es\n"
                            "precision mediump float;\n"
                            "in vec4 aColor;\n"
                            "out vec4 fragColor;\n"
                            "void main() {\n"
                            "     fragColor = aColor;\n"
                            "}";


JNIEXPORT void JNICALL init(JNIEnv *env, jobject obj) {

}

//書寫本地方法的具體邏輯
/**初始化
 *
 * @param env
 * @param obj
*/
JNIEXPORT void JNICALL surfaceCreated(JNIEnv *env, jobject obj) {
    //設(shè)置背景顏色為黑色
    glClearColor(0, 0, 0, 0);
    //創(chuàng)建頂點(diǎn)著色器
    vertexShader = LoadShader(GL_VERTEX_SHADER, vertexShaderCode);
    //創(chuàng)建片元著色器
    fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fragmentShaderCode);
    //將頂點(diǎn)著色器和片元著色器交給統(tǒng)一程序管理
    mProgram = linkProgram(vertexShader, fragmentShader);
}

/**圖形尺寸
 *
 * @param env
 * @param obj
 * @param width
 * @param height
*/
glm::mat4 mProjectionMatrix;
glm::mat4 mViewMatrix;
glm::mat4 mMVPMatrix;
float mMVPMatrixArray[16];

JNIEXPORT void JNICALL surfaceChanged(JNIEnv *env, jobject obj, jint width, jint height) {
    //設(shè)置視口
    glViewport(0, 0, width, height);
    //寬高比
    float ratio = (float) width / height;
    //透視投影矩陣
    mProjectionMatrix = glm::frustum(-ratio, ratio, -1.0f, 1.0f, 3.0f,
                                   7.0f); //ratio 一般表示視口的寬高比,width/height
    //相機(jī)位置
    mViewMatrix = glm::lookAt(glm::vec3(3, 3, 3), // 相機(jī)位置
                              glm::vec3(0, 0, 0), // 觀察點(diǎn)坐標(biāo)
                              glm::vec3(1, 0, 1));
    //矩陣合并
    mMVPMatrix = mProjectionMatrix * mViewMatrix;
    //矩陣轉(zhuǎn)換成數(shù)組
    int m = 0;
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++) {
            mMVPMatrixArray[m] = mMVPMatrix[i][j];
            m++;
        }
}


/**渲染繪制
 *
 * @param env
 * @param obj
*/
JNIEXPORT void JNICALL drawFrame(JNIEnv *env, jobject obj) {
    //清除顏色緩沖區(qū)和深度緩沖區(qū)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //開啟深度測(cè)試
    glEnable(GL_DEPTH_TEST);
    //使用統(tǒng)一的管理程序
    glUseProgram(mProgram);
    //獲取變換矩陣vMatrix成員句柄
    //圖形參數(shù)
    GLint mMatrixHandler = glGetUniformLocation(mProgram, "vMatrix");
    //指定vMatrix的值
    glUniformMatrix4fv(mMatrixHandler, 1, false, mMVPMatrixArray);
    //獲取頂點(diǎn)著色器的vPosition成員句柄
    GLint mPositionHandle = glGetAttribLocation(mProgram, "vPosition");
    //啟用頂點(diǎn)的句柄
    glEnableVertexAttribArray(mPositionHandle);
    //準(zhǔn)備坐標(biāo)數(shù)據(jù)
    glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                                 GL_FLOAT, false,
            vertexStride, vertexPoints);
    //獲取片元著色器的vColor成員的句柄
    //因?yàn)槭遣噬?,?shù)據(jù)類型和頂點(diǎn)類似,所以必須是glGetAttribLocation方法
    //glGetUniformLocation方法畫不全顏色,會(huì)變成黑色
    GLint mColorHandle = glGetAttribLocation(mProgram, "vColor");
    //啟動(dòng)顏色的句柄
    glEnableVertexAttribArray(mColorHandle);
    //設(shè)置圖形的顏色
    //準(zhǔn)備顏色數(shù)據(jù)
    glVertexAttribPointer(mColorHandle, COORDS_PER_COLOR,
                                 GL_FLOAT, false,
            colorStride, colors);
    //繪制圖形
    glLineWidth(10.0f);
    //索引法繪制圖形,索引繪制三角形,無需在用扇形,直接繪制即可
    glDrawElements(GL_TRIANGLES, getArrayLen(index),
            GL_UNSIGNED_SHORT, index);
    //禁止顏色數(shù)組的句柄
    glDisableVertexAttribArray(mColorHandle);
    //禁止頂點(diǎn)數(shù)組的句柄
    glDisableVertexAttribArray(mPositionHandle);
}


/**加載著色器
 *
 */
JNIEXPORT GLuint LoadShader(int type, char *shaderCode) {
    //創(chuàng)建一個(gè)著色器
    GLuint shader = glCreateShader(type);
    if (shader != 0) {
        //加載到著色器
        glShaderSource(shader, 1, &shaderCode, NULL);
        //編譯著色器
        glCompileShader(shader);
        //檢測(cè)狀態(tài)
        GLint compileStatus;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
        if (compileStatus == 0) {
            //聲明log長度變量
            GLint infoLen = 0;
            //獲取長度并賦值
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen > 1) {
                //創(chuàng)建成功小于等于1
                char *infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
                glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
                printf("SHADER ERROR!");
                free(infoLog);
            }
            //創(chuàng)建失敗
            glDeleteShader(shader);
            return 0;
        }
        return shader;
    } else {
        //創(chuàng)建失敗
        return 0;
    }
}

/**鏈接著色器
 *
 */
JNIEXPORT GLuint linkProgram(GLuint vertexShader, GLuint fragmentShader) {
    GLuint program = glCreateProgram();
    if (program != 0) {
        //將頂點(diǎn)著色器加入到程序
        glAttachShader(program, vertexShader);
        //將片元著色器加入到程序中
        glAttachShader(program, fragmentShader);
        //鏈接著色器程序
        glLinkProgram(program);
        //檢測(cè)狀態(tài)
        GLint linkStatus;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
        if (linkStatus == 0) {
            GLint infoLen = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen > 1) {
                char *infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
                glGetProgramInfoLog(program, infoLen, NULL, infoLog);
                printf("PROGRAM ERROR!");
                free(infoLog);
            }
            glDeleteProgram(program);
            return 0;
        }
        return program;
    } else {
        //創(chuàng)建失敗
        return 0;
    }
}

/** 動(dòng)態(tài)注冊(cè)
* @param env
 * @return
*/
//本地方法聲明和具體邏輯連接
JNINativeMethod methods[] = {
        {"init",           "()V",   (void *) init},
        {"surfaceCreated", "()V",   (void *) surfaceCreated},
        {"surfaceChanged", "(II)V", (void *) surfaceChanged},
        {"drawFrame",      "()V",   (void *) drawFrame}
};

/** 動(dòng)態(tài)注冊(cè)
* @param env
* @return
*/
jint registerNativeMethod(JNIEnv *env) {
    //到本地方法存在的類找出其方法聲明
    jclass cl = env->FindClass("com/example/openglndk/WaveRenderer");
    if ((env->RegisterNatives(cl, methods, sizeof(methods) / sizeof(methods[0]))) < 0) {
        return -1;
    }
    return 0;
}

/** 加載默認(rèn)回調(diào)
* @param vm
* @param reserved
* @return
*/
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    //注冊(cè)方法
    if (registerNativeMethod(env) != JNI_OK) {
        return -1;
    }
    return JNI_VERSION_1_6;
}

繪制球體

JAVA版本

  • Renderer類
package com.example.openglndk;

import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class MyRenderer implements GLSurfaceView.Renderer {
    //坐標(biāo)個(gè)數(shù)(xyz)
    private final static int COORDS_PER_VERTEX = 3;

    //頂點(diǎn)之間的偏移量
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)

    private float radius = 0.5f; //半徑

    private FloatBuffer vertexBuffer;

    private int vertexShader;
    private int fragmentShader;
    private int mProgram;

    private int vertexCount;

    //定義點(diǎn)坐標(biāo)
    private float vertexPoints[];

    //設(shè)置顏色,依次為紅綠藍(lán)和透明通道
    private float color[] = {0.1f, 0.9f, 1.0f, 0.0f};

    //根據(jù)經(jīng)緯度創(chuàng)建球體頂點(diǎn)坐標(biāo)
    private float[] createPositions() {
        //球以(0,0,0)為中心,以R為半徑,則球上任意一點(diǎn)的坐標(biāo)為
        // 其中,a為圓心到點(diǎn)的線段與xz平面的夾角,b為圓心到點(diǎn)的線段在xz平面的投影與z軸的夾角
        ArrayList<Float> data = new ArrayList<>();
        float r1, r2;
        float h1, h2;
        float sin, cos;
        float step = 1.0f;
        // 遍歷緯度
        for (float i = -90; i < 90 + step; i += step) {
            //Math.sin(x)  x 的正玄值。返回值在 -1.0 到 1.0 之間;X 都是指的“弧度”而非“角度”,弧度的計(jì)算公式為: 2*PI/360*角度
            //計(jì)算當(dāng)前點(diǎn)與圓心連線,與Y軸夾角θ的正余弦值(此坐標(biāo)系為openGL坐標(biāo)系)
            /**
             * 以下坐標(biāo)系為openGl坐標(biāo)系
             * 此處計(jì)算當(dāng)前緯度與Z軸夾角的正余弦值,由于根據(jù)公式,應(yīng)該計(jì)算與Y軸的正余弦,但因?yàn)榛ビ鄪A角sin與cos相等,所以按此計(jì)算沒有問題
             * 后續(xù)的X的坐標(biāo)就變成了x=R*cos*cos,所有關(guān)于θ的角的sin值都變換為cos計(jì)算
             */
            r1 = (float) (radius * Math.cos(i * Math.PI / 180.0));
            r2 = (float) (radius * Math.cos((i + step) * Math.PI / 180.0));
            h1 = (float) (radius * Math.sin(i * Math.PI / 180.0));
            h2 = (float) (radius * Math.sin((i + step) * Math.PI / 180.0));
            // 固定緯度, 360 度旋轉(zhuǎn)遍歷一條緯線
            float step2 = step * 2;
            for (float j = 0.0f; j < 360.0f + step; j += step2) {
                // 計(jì)算當(dāng)前點(diǎn)在XZ平面投影,與Z軸的夾角φ的正余弦值(此坐標(biāo)系為openGL坐標(biāo)系)
                cos = (float) Math.cos(j * Math.PI / 180.0);
                sin = (float) Math.sin(j * Math.PI / 180.0);

                data.add(r2 * cos);
                data.add(h2);
                data.add(r2 * sin);
                data.add(r1 * cos);
                data.add(h1);
                data.add(r1 * sin);
            }
        }
        float[] f = new float[data.size()];
        for (int i = 0; i < f.length; i++) {
            f[i] = data.get(i);
        }
        return f;
    }

    private final String vertexShaderCode =
            "attribute vec4 vPosition;" +
                    "uniform mat4 vMatrix;" +
                    "void main() {" +
                    "  gl_Position = vMatrix*vPosition;" +
                    "  gl_PointSize = 10.0;" +
                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";


    public MyRenderer() {
        vertexPoints = createPositions();
        vertexCount = vertexPoints.length / COORDS_PER_VERTEX;
        //坐標(biāo)
        vertexBuffer = ByteBuffer.allocateDirect(
                vertexPoints.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        vertexBuffer.put(vertexPoints);
        vertexBuffer.position(0);
    }

    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
        GLES30.glClearColor(1, 1, 1, 1);
        vertexShader = LoadShader(GLES30.GL_VERTEX_SHADER,
                vertexShaderCode);
        fragmentShader = LoadShader(GLES30.GL_FRAGMENT_SHADER,
                fragmentShaderCode);
        mProgram = linkProgram(vertexShader, fragmentShader);
    }


    private float mProjectionMatrix[] = new float[16];
    private float mViewMatrix[] = new float[16];
    private float mMVPMatrix[] = new float[16];

    @Override
    public void onSurfaceChanged(GL10 gl10, int width, int height) {
        GLES30.glViewport(0, 0, width, height);
        //寬高比
        float ratio = (float) width / height;
        //設(shè)置投影矩陣
        Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
        //設(shè)置相機(jī)角度
        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
        //矩陣合并
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
    }

    //每20ms刷新
    @Override
    public void onDrawFrame(GL10 gl10) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
        //將程序加入
        GLES30.glUseProgram(mProgram);
        //獲取變換矩陣vMatrix成員句柄
        //圖形參數(shù)
        int mMatrixHandler = GLES30.glGetUniformLocation(mProgram, "vMatrix");
        //指定vMatrix的值
        GLES30.glUniformMatrix4fv(mMatrixHandler, 1, false, mMVPMatrix, 0);
        //獲取頂點(diǎn)著色器的vPosition成員句柄
        int mPositionHandle = GLES30.glGetAttribLocation(mProgram, "vPosition");
        //啟用頂點(diǎn)的句柄
        GLES30.glEnableVertexAttribArray(mPositionHandle);
        //準(zhǔn)備坐標(biāo)數(shù)據(jù)
        GLES30.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                GLES30.GL_FLOAT, false,
                vertexStride, vertexBuffer);
        //獲取片元著色器的vColor成員的句柄
        int mColorHandle = GLES30.glGetUniformLocation(mProgram, "vColor");
        //設(shè)置圖形的顏色
        GLES30.glUniform4fv(mColorHandle, 1, color, 0);
        //頂點(diǎn)法繪制圖形
//        GLES30.glLineWidth(10.0f);
        GLES30.glDrawArrays(GLES30.GL_LINE_LOOP, 0, vertexCount);
        //禁止頂點(diǎn)數(shù)組的句柄
        GLES30.glDisableVertexAttribArray(mPositionHandle);
    }

    /**
     * 編譯
     *
     * @param type       頂點(diǎn)著色器:GLES30.GL_VERTEX_SHADER
     *                   片段著色器:GLES30.GL_FRAGMENT_SHADER
     * @param shaderCode
     * @return
     */
    private static int LoadShader(int type, String shaderCode) {
        //創(chuàng)建一個(gè)著色器
        final int shaderId = GLES30.glCreateShader(type);
        if (shaderId != 0) {
            //加載到著色器
            GLES30.glShaderSource(shaderId, shaderCode);
            //編譯著色器
            GLES30.glCompileShader(shaderId);
            //檢測(cè)狀態(tài)
            final int[] compileStatus = new int[1];
            GLES30.glGetShaderiv(shaderId, GLES30.GL_COMPILE_STATUS, compileStatus, 0);
            if (compileStatus[0] == 0) {
                String logInfo = GLES30.glGetShaderInfoLog(shaderId);
                System.err.println(logInfo);
                //創(chuàng)建失敗
                GLES30.glDeleteShader(shaderId);
                return 0;
            }
            return shaderId;
        } else {
            //創(chuàng)建失敗
            return 0;
        }
    }

    /**
     * 鏈接小程序
     *
     * @param vertexShaderId   頂點(diǎn)著色器
     * @param fragmentShaderId 片段著色器
     * @return
     */
    public static int linkProgram(int vertexShaderId, int fragmentShaderId) {
        final int programId = GLES30.glCreateProgram();
        if (programId != 0) {
            //將頂點(diǎn)著色器加入到程序
            GLES30.glAttachShader(programId, vertexShaderId);
            //將片元著色器加入到程序中
            GLES30.glAttachShader(programId, fragmentShaderId);
            //鏈接著色器程序
            GLES30.glLinkProgram(programId);
            final int[] linkStatus = new int[1];
            GLES30.glGetProgramiv(programId, GLES30.GL_LINK_STATUS, linkStatus, 0);
            if (linkStatus[0] == 0) {
                String logInfo = GLES30.glGetProgramInfoLog(programId);
                System.err.println(logInfo);
                GLES30.glDeleteProgram(programId);
                return 0;
            }
            return programId;
        } else {
            //創(chuàng)建失敗
            return 0;
        }
    }
}

C++版本

  • .cpp文件
//
// Created by lvjunkai on 2022/2/21.
//
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <jni.h>
#include <malloc.h>
#include <vector>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/glm.hpp>

//命名空間
using namespace std;

//定義宏
//#define PI 3.1415926;
//常數(shù)Π
const double PI = acos(-1.0);

//聲明自定義函數(shù)
//創(chuàng)建編譯加載
GLuint LoadShader(int type, char *shaderCode);

//鏈接統(tǒng)一程序
GLuint linkProgram(GLuint vertexShader, GLuint fragmentShader);

//模板技術(shù)定義的函數(shù)
//用于求數(shù)組長度
template<class T>
GLsizei getArrayLen(T &array) {
    return (sizeof(array) / sizeof(array[0]));
}

//坐標(biāo)個(gè)數(shù)(xyz)
const GLint COORDS_PER_VERTEX = 3;

//頂點(diǎn)之間的偏移量
const GLsizei vertexStride = COORDS_PER_VERTEX * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)

//聲明頂點(diǎn)著色器
GLuint vertexShader;
//聲明片元著色器
GLuint fragmentShader;
//聲明著色器管理程序
GLuint mProgram;

//定義圖形坐標(biāo)
vector<float> vertexVector;  //存放頂點(diǎn)數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)
float vertexPoints[196566];  //頂點(diǎn)數(shù)組
float radius = 0.5f; //半徑

//頂點(diǎn)個(gè)數(shù)
GLsizei vertexCount = getArrayLen(vertexPoints) / COORDS_PER_VERTEX;


//設(shè)置顏色,依次為紅綠藍(lán)和透明通道
float color[] = {0.1f, 0.9f, 1.0f, 0.0f};


//頂點(diǎn)著色器代碼
char vertexShaderCode[] = "attribute vec4 vPosition;"
                          "uniform mat4 vMatrix;"
                          "void main() {"
                          "  gl_Position = vMatrix*vPosition;"
                          "  gl_PointSize = 10.0;"
                          "}";

//片段著色器代碼
char fragmentShaderCode[] = "precision mediump float;"
                            "uniform vec4 vColor;"
                            "void main() {"
                            "  gl_FragColor = vColor;"
                            "}";

//創(chuàng)建頂點(diǎn)坐標(biāo)放入vector數(shù)據(jù)結(jié)構(gòu)中
vector<float> createPositions() {
    //球以(0,0,0)為中心,以R為半徑,則球上任意一點(diǎn)的坐標(biāo)為
    // 其中,a為圓心到點(diǎn)的線段與xz平面的夾角,b為圓心到點(diǎn)的線段在xz平面的投影與z軸的夾角
    vector<float> data;
    float r1, r2;
    float h1, h2;
    float sin1, cos1;
    float step = 1.0f;
    // 遍歷緯度
    for (float i = -90; i < 90 + step; i += step) {
        //Math.sin(x)  x 的正玄值。返回值在 -1.0 到 1.0 之間;X 都是指的“弧度”而非“角度”,弧度的計(jì)算公式為: 2*PI/360*角度
        //計(jì)算當(dāng)前點(diǎn)與圓心連線,與Y軸夾角θ的正余弦值(此坐標(biāo)系為openGL坐標(biāo)系)
        /**
         * 以下坐標(biāo)系為openGl坐標(biāo)系
         * 此處計(jì)算當(dāng)前緯度與Z軸夾角的正余弦值,由于根據(jù)公式,應(yīng)該計(jì)算與Y軸的正余弦,但因?yàn)榛ビ鄪A角sin與cos相等,所以按此計(jì)算沒有問題
         * 后續(xù)的X的坐標(biāo)就變成了x=R*cos*cos,所有關(guān)于θ的角的sin值都變換為cos計(jì)算
         */
        r1 = (float) (radius * cos(i * PI / 180.0));
        r2 = (float) (radius * cos((i + step) * PI / 180.0));
        h1 = (float) (radius * sin(i * PI / 180.0));
        h2 = (float) (radius * sin((i + step) * PI / 180.0));
        // 固定緯度, 360 度旋轉(zhuǎn)遍歷一條緯線
        float step2 = step * 2;
        for (float j = 0.0f; j < 360.0f + step; j += step2) {
            // 計(jì)算當(dāng)前點(diǎn)在XZ平面投影,與Z軸的夾角φ的正余弦值(此坐標(biāo)系為openGL坐標(biāo)系)
            cos1 = (float) cos(j * PI / 180.0);
            sin1 = (float) sin(j * PI / 180.0);

            data.push_back(r2 * cos1);
            data.push_back(h2);
            data.push_back(r2 * sin1);
            data.push_back(r1 * cos1);
            data.push_back(h1);
            data.push_back(r1 * sin1);
        }
    }
    return data;
}


JNIEXPORT void JNICALL init(JNIEnv *env, jobject obj) {
    //拿到頂點(diǎn)數(shù)據(jù)
    vertexVector = createPositions();
    //創(chuàng)建迭代器
    vector<float>::iterator t;
    int i = 0;
    //迭代器遍歷vector中的數(shù)據(jù)
    //將其中數(shù)據(jù)放入數(shù)組中,形成頂點(diǎn)坐標(biāo)
    for (t = vertexVector.begin(); t != vertexVector.end(); t++) {
        vertexPoints[i] = *t;
        i++;
    }
}

//書寫本地方法的具體邏輯
/**初始化
 *
 * @param env
 * @param obj
*/
JNIEXPORT void JNICALL surfaceCreated(JNIEnv *env, jobject obj) {
    //設(shè)置背景顏色為黑色
    glClearColor(0, 0, 0, 0);
    //創(chuàng)建頂點(diǎn)著色器
    vertexShader = LoadShader(GL_VERTEX_SHADER, vertexShaderCode);
    //創(chuàng)建片元著色器
    fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fragmentShaderCode);
    //將頂點(diǎn)著色器和片元著色器交給統(tǒng)一程序管理
    mProgram = linkProgram(vertexShader, fragmentShader);
}

/**圖形尺寸
 *
 * @param env
 * @param obj
 * @param width
 * @param height
*/
glm::mat4 mProjectionMatrix;
glm::mat4 mViewMatrix;
glm::mat4 mMVPMatrix;

JNIEXPORT void JNICALL surfaceChanged(JNIEnv *env, jobject obj, jint width, jint height) {
    //設(shè)置視口
    glViewport(0, 0, width, height);
    //寬高比
    float ratio = (float) width / height;
    //二維圖形設(shè)置正交投影矩陣即可
    //frustum投影看不見圖像,ortho投影才看的到球
    mProjectionMatrix = glm::ortho(-ratio, ratio, -1.0f, 1.0f, 0.0f,
                                     100.0f); //ratio 一般表示視口的寬高比,width/height
    //相機(jī)位置
    mViewMatrix = glm::lookAt(glm::vec3(0, 0, -3), //  相機(jī)位置
                              glm::vec3(0, 0, 0), // 觀察點(diǎn)坐標(biāo)
                              glm::vec3(0, 1, 0));
    //矩陣合并
    mMVPMatrix = mProjectionMatrix * mViewMatrix;
}


/**渲染繪制
 *
 * @param env
 * @param obj
*/
JNIEXPORT void JNICALL drawFrame(JNIEnv *env, jobject obj) {
    //清除顏色緩沖區(qū)
    glClear(GL_COLOR_BUFFER_BIT);
    //使用程序
    glUseProgram(mProgram);
    //獲取變換矩陣vMatrix成員句柄
    GLint mMatrixHandler = glGetUniformLocation(mProgram, "vMatrix");
    //矩陣轉(zhuǎn)換成數(shù)組
    float mMVPMatrixArray[16];
    int m = 0;
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++) {
            mMVPMatrixArray[m] = mMVPMatrix[i][j];
            m++;
        }
    //指定vMatrix的值
    glUniformMatrix4fv(mMatrixHandler, 1, false, mMVPMatrixArray);
    //獲取頂點(diǎn)著色器的vPosition成員句柄
    GLint mPositionHandle = glGetAttribLocation(mProgram, "vPosition");
    //啟用圖形頂點(diǎn)的句柄
    glEnableVertexAttribArray(mPositionHandle);
    //準(zhǔn)備圖形的坐標(biāo)數(shù)據(jù)
    glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GL_FLOAT, GL_FALSE, vertexStride,
                          vertexPoints);
    //獲取片元著色器的vColor成員的句柄
    GLint mColorHandle = glGetUniformLocation(mProgram, "vColor");
    //設(shè)置繪制圖形的顏色
    glUniform4fv(mColorHandle, 1, color);
    //繪制圖形
    glLineWidth(0.5f);
    glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
    //禁止頂點(diǎn)數(shù)組的句柄
    glDisableVertexAttribArray(mPositionHandle);
}


/**加載著色器
 *
 */
JNIEXPORT GLuint LoadShader(int type, char *shaderCode) {
    //創(chuàng)建一個(gè)著色器
    GLuint shader = glCreateShader(type);
    if (shader != 0) {
        //加載到著色器
        glShaderSource(shader, 1, &shaderCode, NULL);
        //編譯著色器
        glCompileShader(shader);
        //檢測(cè)狀態(tài)
        GLint compileStatus;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
        if (compileStatus == 0) {
            //聲明log長度變量
            GLint infoLen = 0;
            //獲取長度并賦值
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen > 1) {
                //創(chuàng)建成功小于等于1
                char *infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
                glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
                printf("SHADER ERROR!");
                free(infoLog);
            }
            //創(chuàng)建失敗
            glDeleteShader(shader);
            return 0;
        }
        return shader;
    } else {
        //創(chuàng)建失敗
        return 0;
    }
}

/**鏈接著色器
 *
 */
JNIEXPORT GLuint linkProgram(GLuint vertexShader, GLuint fragmentShader) {
    GLuint program = glCreateProgram();
    if (program != 0) {
        //將頂點(diǎn)著色器加入到程序
        glAttachShader(program, vertexShader);
        //將片元著色器加入到程序中
        glAttachShader(program, fragmentShader);
        //鏈接著色器程序
        glLinkProgram(program);
        //檢測(cè)狀態(tài)
        GLint linkStatus;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
        if (linkStatus == 0) {
            GLint infoLen = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen > 1) {
                char *infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
                glGetProgramInfoLog(program, infoLen, NULL, infoLog);
                printf("PROGRAM ERROR!");
                free(infoLog);
            }
            glDeleteProgram(program);
            return 0;
        }
        return program;
    } else {
        //創(chuàng)建失敗
        return 0;
    }
}

/** 動(dòng)態(tài)注冊(cè)
* @param env
 * @return
*/
//本地方法聲明和具體邏輯連接
JNINativeMethod methods[] = {
        {"init",           "()V",   (void *) init},
        {"surfaceCreated", "()V",   (void *) surfaceCreated},
        {"surfaceChanged", "(II)V", (void *) surfaceChanged},
        {"drawFrame",      "()V",   (void *) drawFrame}
};

/** 動(dòng)態(tài)注冊(cè)
* @param env
* @return
*/
jint registerNativeMethod(JNIEnv *env) {
    //到本地方法存在的類找出其方法聲明
    jclass cl = env->FindClass("com/example/openglndk/WaveRenderer");
    if ((env->RegisterNatives(cl, methods, sizeof(methods) / sizeof(methods[0]))) < 0) {
        return -1;
    }
    return 0;
}

/** 加載默認(rèn)回調(diào)
* @param vm
* @param reserved
* @return
*/
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    //注冊(cè)方法
    if (registerNativeMethod(env) != JNI_OK) {
        return -1;
    }
    return JNI_VERSION_1_6;
}

繪制圓環(huán)

JAVA版本

  • Renderer類
package com.example.openglndk;

import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class MyRenderer implements GLSurfaceView.Renderer {
    //坐標(biāo)個(gè)數(shù)(xyz)
    private final static int COORDS_PER_VERTEX = 3;

    //頂點(diǎn)之間的偏移量
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)

    private FloatBuffer vertexBuffer;

    private int vertexShader;
    private int fragmentShader;
    private int mProgram;

    //聲明點(diǎn)坐標(biāo)
    private float vertexPoints[];
    //點(diǎn)的數(shù)量
    private int vertexCount;

    //設(shè)置顏色,依次為紅綠藍(lán)和透明通道
    //黑色
    private float color[] = {0.0f, 0.0f, 0.0f, 0.0f};

    //創(chuàng)建所有點(diǎn)
    private float[] createPositions() {
        List<Float> coords = new ArrayList<Float>();
        float Rinner = 0.2f;//內(nèi)圓半徑
        float Rring = 0.3f;//環(huán)半徑
        int count = 20;//循環(huán)次數(shù)
        float alpha = 0;//外圓角度
        float x0, x1, y0, y1, z0, z1;
        float alphaStep = (float) (2 * Math.PI / count);//alpha角的步長(外部圓環(huán))
        float betaStep = (float) (2 * Math.PI / count);//beta角的步長(每個(gè)切片)
        float beta = 0;//切片循環(huán)角度
        int count0 = 20;//循環(huán)次數(shù)
        /***************************外層循環(huán)主要負(fù)責(zé)把圓環(huán)切成幾個(gè)部分*******************************/
        for (int i = 0; i < count; i++) {
            alpha = i * alphaStep;
            /***************************內(nèi)層循環(huán)主要負(fù)責(zé)把每個(gè)部分畫出來*******************************/

            for (int j = 0; j <= count0; j++) {
                beta = j * betaStep;
                x0 = (float) (Math.cos(alpha) * (Rring + Rinner + Rinner * Math.cos(beta)));
                y0 = (float) (Math.sin(alpha) * (Rring + Rinner + Rinner * Math.cos(beta)));
                z0 = (float) -(Rring * Math.sin(beta));

                x1 = (float) (Math.cos(alpha + alphaStep) * (Rring + Rinner + Rinner * Math.cos(beta)));
                y1 = (float) (Math.sin(alpha + alphaStep) * (Rring + Rinner + Rinner * Math.cos(beta)));
                z1 = (float) (-Rring * Math.sin(beta));

                coords.add(x0);
                coords.add(y0);
                coords.add(z0);
                coords.add(x1);
                coords.add(y1);
                coords.add(z1);
            }
        }
        float[] f = new float[coords.size()];    //所有的頂點(diǎn)
        for (int i = 0; i < f.length; i++) {
            f[i] = coords.get(i);
        }
        return f;
    }

    private final String vertexShaderCode =
            "attribute vec4 vPosition;" +
                    "uniform mat4 vMatrix;" +
                    "void main() {" +
                    "  gl_Position = vMatrix*vPosition;" +
                    "  gl_PointSize = 10.0;" +
                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";

    public MyRenderer() {
        vertexPoints = createPositions();
        vertexCount = vertexPoints.length / COORDS_PER_VERTEX;
        //坐標(biāo)
        vertexBuffer = ByteBuffer.allocateDirect(
                vertexPoints.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        vertexBuffer.put(vertexPoints);
        vertexBuffer.position(0);
    }

    @Override
    public void onSurfaceCreated (GL10 gl10, EGLConfig eglConfig){
        //設(shè)置背景為白色
        GLES30.glClearColor(1, 1, 1, 1);
        vertexShader = LoadShader(GLES30.GL_VERTEX_SHADER,
                vertexShaderCode);
        fragmentShader = LoadShader(GLES30.GL_FRAGMENT_SHADER,
                fragmentShaderCode);
        mProgram = linkProgram(vertexShader, fragmentShader);
    }


    private float mProjectionMatrix[] = new float[16];
    private float mViewMatrix[] = new float[16];
    private float mMVPMatrix[] = new float[16];

    @Override
    public void onSurfaceChanged (GL10 gl10,int width, int height){
        GLES30.glViewport(0, 0, width, height);
        //寬高比
        float ratio = (float) width / height;
        //設(shè)置投影矩陣
        Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
        //設(shè)置相機(jī)角度(核心)
        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
        //矩陣合并
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
    }

    //每20ms刷新
    @Override
    public void onDrawFrame (GL10 gl10){
        //清除顏色緩沖區(qū)
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
        //將程序加入
        GLES30.glUseProgram(mProgram);
        //獲取變換矩陣vMatrix成員句柄
        //圖形參數(shù)
        int mMatrixHandler = GLES30.glGetUniformLocation(mProgram, "vMatrix");
        //指定vMatrix的值
        GLES30.glUniformMatrix4fv(mMatrixHandler, 1, false, mMVPMatrix, 0);
        //獲取頂點(diǎn)著色器的vPosition成員句柄
        int mPositionHandle = GLES30.glGetAttribLocation(mProgram, "vPosition");
        //啟用頂點(diǎn)的句柄
        GLES30.glEnableVertexAttribArray(mPositionHandle);
        //準(zhǔn)備坐標(biāo)數(shù)據(jù)
        GLES30.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                GLES30.GL_FLOAT, false,
                vertexStride, vertexBuffer);
        //獲取片元著色器的vColor成員的句柄
        int mColorHandle = GLES30.glGetUniformLocation(mProgram, "vColor");
        //設(shè)置圖形的顏色
        GLES30.glUniform4fv(mColorHandle, 1, color, 0);
        //繪制圖形
        GLES30.glDrawArrays(GLES30.GL_LINE_STRIP, 0, vertexCount);
        //禁止頂點(diǎn)數(shù)組的句柄
        GLES30.glDisableVertexAttribArray(mPositionHandle);
    }

    /**
     * 編譯
     *
     * @param type       頂點(diǎn)著色器:GLES30.GL_VERTEX_SHADER
     *                   片段著色器:GLES30.GL_FRAGMENT_SHADER
     * @param shaderCode
     * @return
     */
    private static int LoadShader ( int type, String shaderCode){
        //創(chuàng)建一個(gè)著色器
        final int shaderId = GLES30.glCreateShader(type);
        if (shaderId != 0) {
            //加載到著色器
            GLES30.glShaderSource(shaderId, shaderCode);
            //編譯著色器
            GLES30.glCompileShader(shaderId);
            //檢測(cè)狀態(tài)
            final int[] compileStatus = new int[1];
            GLES30.glGetShaderiv(shaderId, GLES30.GL_COMPILE_STATUS, compileStatus, 0);
            if (compileStatus[0] == 0) {
                String logInfo = GLES30.glGetShaderInfoLog(shaderId);
                System.err.println(logInfo);
                //創(chuàng)建失敗
                GLES30.glDeleteShader(shaderId);
                return 0;
            }
            return shaderId;
        } else {
            //創(chuàng)建失敗
            return 0;
        }
    }

    /**
     * 鏈接小程序
     *
     * @param vertexShaderId   頂點(diǎn)著色器
     * @param fragmentShaderId 片段著色器
     * @return
     */
    public static int linkProgram ( int vertexShaderId, int fragmentShaderId){
        final int programId = GLES30.glCreateProgram();
        if (programId != 0) {
            //將頂點(diǎn)著色器加入到程序
            GLES30.glAttachShader(programId, vertexShaderId);
            //將片元著色器加入到程序中
            GLES30.glAttachShader(programId, fragmentShaderId);
            //鏈接著色器程序
            GLES30.glLinkProgram(programId);
            final int[] linkStatus = new int[1];
            GLES30.glGetProgramiv(programId, GLES30.GL_LINK_STATUS, linkStatus, 0);
            if (linkStatus[0] == 0) {
                String logInfo = GLES30.glGetProgramInfoLog(programId);
                System.err.println(logInfo);
                GLES30.glDeleteProgram(programId);
                return 0;
            }
            return programId;
        } else {
            //創(chuàng)建失敗
            return 0;
        }
    }
}

C++版本

  • .cpp文件
//
// Created by lvjunkai on 2022/2/21.
//
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <jni.h>
#include <malloc.h>
#include <vector>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/glm.hpp>

//命名空間
using namespace std;

//定義宏
//#define PI 3.1415926;
//常數(shù)Π
const double PI = acos(-1.0);

//聲明自定義函數(shù)
//創(chuàng)建編譯加載
GLuint LoadShader(int type, char *shaderCode);

//鏈接統(tǒng)一程序
GLuint linkProgram(GLuint vertexShader, GLuint fragmentShader);

//模板技術(shù)定義的函數(shù)
//用于求數(shù)組長度
template<class T>
GLsizei getArrayLen(T &array) {
    return (sizeof(array) / sizeof(array[0]));
}

//坐標(biāo)個(gè)數(shù)(xyz)
const GLint COORDS_PER_VERTEX = 3;

//頂點(diǎn)之間的偏移量
const GLsizei vertexStride = COORDS_PER_VERTEX * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)

//聲明頂點(diǎn)著色器
GLuint vertexShader;
//聲明片元著色器
GLuint fragmentShader;
//聲明著色器管理程序
GLuint mProgram;

//定義圖形坐標(biāo)
vector<float> vertexVector;  //存放頂點(diǎn)數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)
float vertexPoints[196566];  //頂點(diǎn)數(shù)組

//頂點(diǎn)個(gè)數(shù)
GLsizei vertexCount = getArrayLen(vertexPoints) / COORDS_PER_VERTEX;


//設(shè)置顏色,依次為紅綠藍(lán)和透明通道
float color[] = {0.1f, 0.9f, 1.0f, 0.0f};


//頂點(diǎn)著色器代碼
char vertexShaderCode[] = "attribute vec4 vPosition;"
                          "uniform mat4 vMatrix;"
                          "void main() {"
                          "  gl_Position = vMatrix*vPosition;"
                          "  gl_PointSize = 10.0;"
                          "}";

//片段著色器代碼
char fragmentShaderCode[] = "precision mediump float;"
                            "uniform vec4 vColor;"
                            "void main() {"
                            "  gl_FragColor = vColor;"
                            "}";

//創(chuàng)建頂點(diǎn)坐標(biāo)放入vector數(shù)據(jù)結(jié)構(gòu)中
vector<float> createPositions() {
    vector<float> coords;
    float Rinner = 0.2f;//環(huán)半徑
    float Rring = 0.2f;//內(nèi)圓半徑
    int count = 20;//循環(huán)次數(shù)
    float alpha = 0;//外圓角度
    float x0, x1, y0, y1, z0, z1;
    float alphaStep = (float) (2 * PI / count);//alpha角的步長(外部圓環(huán))
    float betaStep = (float) (2 * PI / count);//beta角的步長(每個(gè)切片)
    float beta = 0;//切片循環(huán)角度
    int count0 = 20;//循環(huán)次數(shù)
    /***************************外層循環(huán)主要負(fù)責(zé)把圓環(huán)切成幾個(gè)部分*******************************/
    for (int i = 0; i < count; i++) {
        alpha = i * alphaStep;
        /***************************內(nèi)層循環(huán)主要負(fù)責(zé)把每個(gè)部分畫出來*******************************/

        for (int j = 0; j <= count0; j++) {
            beta = j * betaStep;
            x0 = (float) (cos(alpha) * (Rring + Rinner + Rinner * cos(beta)));
            y0 = (float) (sin(alpha) * (Rring + Rinner + Rinner * cos(beta)));
            z0 = (float) -(Rring * sin(beta));

            x1 = (float) (cos(alpha + alphaStep) * (Rring + Rinner + Rinner * cos(beta)));
            y1 = (float) (sin(alpha + alphaStep) * (Rring + Rinner + Rinner * cos(beta)));
            z1 = (float) (-Rring * sin(beta));

            coords.push_back(x0);
            coords.push_back(y0);
            coords.push_back(z0);
            coords.push_back(x1);
            coords.push_back(y1);
            coords.push_back(z1);
        }
    }
    return coords;
}


JNIEXPORT void JNICALL init(JNIEnv *env, jobject obj) {
    //拿到頂點(diǎn)數(shù)據(jù)
    vertexVector = createPositions();
    //創(chuàng)建迭代器
    vector<float>::iterator t;
    int i = 0;
    //迭代器遍歷vector中的數(shù)據(jù)
    //將其中數(shù)據(jù)放入數(shù)組中,形成頂點(diǎn)坐標(biāo)
    for (t = vertexVector.begin(); t != vertexVector.end(); t++) {
        vertexPoints[i] = *t;
        i++;
    }
}

//書寫本地方法的具體邏輯
/**初始化
 *
 * @param env
 * @param obj
*/
JNIEXPORT void JNICALL surfaceCreated(JNIEnv *env, jobject obj) {
    //設(shè)置背景顏色為黑色
    glClearColor(0, 0, 0, 0);
    //創(chuàng)建頂點(diǎn)著色器
    vertexShader = LoadShader(GL_VERTEX_SHADER, vertexShaderCode);
    //創(chuàng)建片元著色器
    fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fragmentShaderCode);
    //將頂點(diǎn)著色器和片元著色器交給統(tǒng)一程序管理
    mProgram = linkProgram(vertexShader, fragmentShader);
}

/**圖形尺寸
 *
 * @param env
 * @param obj
 * @param width
 * @param height
*/
glm::mat4 mProjectionMatrix;
glm::mat4 mViewMatrix;
glm::mat4 mMVPMatrix;

JNIEXPORT void JNICALL surfaceChanged(JNIEnv *env, jobject obj, jint width, jint height) {
    //設(shè)置視口
    glViewport(0, 0, width, height);
    //寬高比
    float ratio = (float) width / height;
    //二維圖形設(shè)置正交投影矩陣即可
    //frustum投影看不見圖像,ortho投影才看的到球
    mProjectionMatrix = glm::ortho(-ratio, ratio, -1.0f, 1.0f, 0.0f,
                                     100.0f); //ratio 一般表示視口的寬高比,width/height
    //相機(jī)位置
    mViewMatrix = glm::lookAt(glm::vec3(0, 0, -3), //  相機(jī)位置
                              glm::vec3(0, 0, 0), // 觀察點(diǎn)坐標(biāo)
                              glm::vec3(0, 1, 0));
    //矩陣合并
    mMVPMatrix = mProjectionMatrix * mViewMatrix;
}


/**渲染繪制
 *
 * @param env
 * @param obj
*/
JNIEXPORT void JNICALL drawFrame(JNIEnv *env, jobject obj) {
    //清除顏色緩沖區(qū)
    glClear(GL_COLOR_BUFFER_BIT);
    //使用程序
    glUseProgram(mProgram);
    //獲取變換矩陣vMatrix成員句柄
    GLint mMatrixHandler = glGetUniformLocation(mProgram, "vMatrix");
    //矩陣轉(zhuǎn)換成數(shù)組
    float mMVPMatrixArray[16];
    int m = 0;
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++) {
            mMVPMatrixArray[m] = mMVPMatrix[i][j];
            m++;
        }
    //指定vMatrix的值
    glUniformMatrix4fv(mMatrixHandler, 1, false, mMVPMatrixArray);
    //獲取頂點(diǎn)著色器的vPosition成員句柄
    GLint mPositionHandle = glGetAttribLocation(mProgram, "vPosition");
    //啟用圖形頂點(diǎn)的句柄
    glEnableVertexAttribArray(mPositionHandle);
    //準(zhǔn)備圖形的坐標(biāo)數(shù)據(jù)
    glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GL_FLOAT, GL_FALSE, vertexStride,
                          vertexPoints);
    //獲取片元著色器的vColor成員的句柄
    GLint mColorHandle = glGetUniformLocation(mProgram, "vColor");
    //設(shè)置繪制圖形的顏色
    glUniform4fv(mColorHandle, 1, color);
    //繪制圖形
    glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
    //禁止頂點(diǎn)數(shù)組的句柄
    glDisableVertexAttribArray(mPositionHandle);
}


/**加載著色器
 *
 */
JNIEXPORT GLuint LoadShader(int type, char *shaderCode) {
    //創(chuàng)建一個(gè)著色器
    GLuint shader = glCreateShader(type);
    if (shader != 0) {
        //加載到著色器
        glShaderSource(shader, 1, &shaderCode, NULL);
        //編譯著色器
        glCompileShader(shader);
        //檢測(cè)狀態(tài)
        GLint compileStatus;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
        if (compileStatus == 0) {
            //聲明log長度變量
            GLint infoLen = 0;
            //獲取長度并賦值
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen > 1) {
                //創(chuàng)建成功小于等于1
                char *infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
                glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
                printf("SHADER ERROR!");
                free(infoLog);
            }
            //創(chuàng)建失敗
            glDeleteShader(shader);
            return 0;
        }
        return shader;
    } else {
        //創(chuàng)建失敗
        return 0;
    }
}

/**鏈接著色器
 *
 */
JNIEXPORT GLuint linkProgram(GLuint vertexShader, GLuint fragmentShader) {
    GLuint program = glCreateProgram();
    if (program != 0) {
        //將頂點(diǎn)著色器加入到程序
        glAttachShader(program, vertexShader);
        //將片元著色器加入到程序中
        glAttachShader(program, fragmentShader);
        //鏈接著色器程序
        glLinkProgram(program);
        //檢測(cè)狀態(tài)
        GLint linkStatus;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
        if (linkStatus == 0) {
            GLint infoLen = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen > 1) {
                char *infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
                glGetProgramInfoLog(program, infoLen, NULL, infoLog);
                printf("PROGRAM ERROR!");
                free(infoLog);
            }
            glDeleteProgram(program);
            return 0;
        }
        return program;
    } else {
        //創(chuàng)建失敗
        return 0;
    }
}

/** 動(dòng)態(tài)注冊(cè)
* @param env
 * @return
*/
//本地方法聲明和具體邏輯連接
JNINativeMethod methods[] = {
        {"init",           "()V",   (void *) init},
        {"surfaceCreated", "()V",   (void *) surfaceCreated},
        {"surfaceChanged", "(II)V", (void *) surfaceChanged},
        {"drawFrame",      "()V",   (void *) drawFrame}
};

/** 動(dòng)態(tài)注冊(cè)
* @param env
* @return
*/
jint registerNativeMethod(JNIEnv *env) {
    //到本地方法存在的類找出其方法聲明
    jclass cl = env->FindClass("com/example/openglndk/WaveRenderer");
    if ((env->RegisterNatives(cl, methods, sizeof(methods) / sizeof(methods[0]))) < 0) {
        return -1;
    }
    return 0;
}

/** 加載默認(rèn)回調(diào)
* @param vm
* @param reserved
* @return
*/
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    //注冊(cè)方法
    if (registerNativeMethod(env) != JNI_OK) {
        return -1;
    }
    return JNI_VERSION_1_6;
}

繪制圓柱體

圓柱和圓錐比,只修改了點(diǎn)的數(shù)量和坐標(biāo),其他都沒變。

//創(chuàng)建圓柱的所有點(diǎn)
    private float[] createPositions() {
        ArrayList<Float> data = new ArrayList<>();
        //兩個(gè)圓上點(diǎn)
        float angDegSpan = 360f / n;
        for (float i = 0; i < 360 + angDegSpan; i += angDegSpan) {
            data.add((float) (radius * Math.sin(i * Math.PI / 180f)));
            data.add((float) (radius * Math.cos(i * Math.PI / 180f)));
            data.add(0.0f);
            data.add((float) (radius * Math.sin(i * Math.PI / 180f)));
            data.add((float) (radius * Math.cos(i * Math.PI / 180f)));
            data.add(height);
        }
        float[] f = new float[data.size()];    //所有的頂點(diǎn)
        for (int i = 0; i < f.length; i++) {
            f[i] = data.get(i);
        }
        return f;
    }

繪制圓錐體

根據(jù)我近幾日所學(xué),查找資料,找不到為什么我的總是一個(gè)圓,而不是圓錐。然后我回復(fù)了一下所學(xué)東西,回想每一個(gè)函數(shù)意義,回想學(xué)過的立體幾何的數(shù)學(xué)知識(shí),最后發(fā)現(xiàn),是相機(jī)的朝向角度問題,因?yàn)槭菑腪軸往下看的,所以就相當(dāng)于從圓錐頂部看下去,就是一個(gè)圓了。改變相機(jī)角度,讓其從y軸,即側(cè)面看去,就可以看出其圓錐的近似模樣。點(diǎn)是沒有錯(cuò)的,就一個(gè)錐點(diǎn)和底部圓面點(diǎn)。

C++版本

  • 還差相機(jī)設(shè)置不會(huì),投影也不會(huì)。

  • .cpp文件文章來源地址http://www.zghlxwxcb.cn/news/detail-405204.html

//
// Created by lvjunkai on 2022/2/21.
//
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <jni.h>
#include <malloc.h>
#include <vector>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/glm.hpp>

//命名空間
using namespace std;

//常數(shù)Π
const double PI = acos(-1.0);

//聲明自定義函數(shù)
//創(chuàng)建編譯加載
GLuint LoadShader(int type, char *shaderCode);

//鏈接統(tǒng)一程序
GLuint linkProgram(GLuint vertexShader, GLuint fragmentShader);

//模板技術(shù)定義的函數(shù)
//用于求數(shù)組長度
template<class T>
GLsizei getArrayLen(T &array) {
    return (sizeof(array) / sizeof(array[0]));
}


//坐標(biāo)個(gè)數(shù)(xyz)
const GLint COORDS_PER_VERTEX = 3;

//頂點(diǎn)之間的偏移量
const GLsizei vertexStride = COORDS_PER_VERTEX * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)

//聲明頂點(diǎn)著色器
GLuint vertexShader;
//聲明片元著色器
GLuint fragmentShader;
//聲明著色器管理程序
GLuint mProgram;

//定義正方形四點(diǎn)坐標(biāo)
vector<float> vertexVector;  //存放頂點(diǎn)數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)
float vertexPoints[1086];  //頂點(diǎn)數(shù)組
float radius = 0.5f; //半徑
float height = 1.0f; //高度
int n = 360; //切割份數(shù)

//頂點(diǎn)個(gè)數(shù)
GLsizei vertexCount = getArrayLen(vertexPoints) / COORDS_PER_VERTEX;

//設(shè)置顏色,依次為紅綠藍(lán)和透明通道
float color[] = {1.0f, 1.0f, 0.0f, 0.0f};


//頂點(diǎn)著色器代碼
char vertexShaderCode[] = "attribute vec4 vPosition;"
                          "uniform mat4 vMatrix;"
                          "void main() {"
                          "  gl_Position = vMatrix*vPosition;"
                          "  gl_PointSize = 10.0;"
                          "}";

//片段著色器代碼
char fragmentShaderCode[] = "precision mediump float;"
                            "uniform vec4 vColor;"
                            "void main() {"
                            "  gl_FragColor = vColor;"
                            "}";

//創(chuàng)建頂點(diǎn)坐標(biāo)放入vector數(shù)據(jù)結(jié)構(gòu)中
vector<float> createPositions() {
    vector<float> data;
    //錐點(diǎn)
    data.push_back(0.0f);
    data.push_back(0.0f);
    data.push_back(height);
    //圓上點(diǎn)
    float angDegSpan = 360.0f / n;
    for (float i = 0; i < 360 + angDegSpan; i += angDegSpan) {
        data.push_back((float) (radius * sin(i * PI / 180.0f)));
        data.push_back((float) (radius * cos(i * PI / 180.0f)));
        data.push_back(0.0f);
    }
    return data;
}


JNIEXPORT void JNICALL init(JNIEnv *env, jobject obj) {
    //拿到頂點(diǎn)數(shù)據(jù)
    vertexVector = createPositions();
    //創(chuàng)建迭代器
    vector<float>::iterator t;
    int i = 0;
    //迭代器遍歷vector中的數(shù)據(jù)
    //將其中數(shù)據(jù)放入數(shù)組中,形成頂點(diǎn)坐標(biāo)
    for (t = vertexVector.begin(); t != vertexVector.end(); t++) {
        vertexPoints[i] = *t;
        i++;
    }
}

//書寫本地方法的具體邏輯
/**初始化
 *
 * @param env
 * @param obj
*/
JNIEXPORT void JNICALL surfaceCreated(JNIEnv *env, jobject obj) {
    //設(shè)置背景顏色為黑色
    glClearColor(0, 0, 0, 0);
    //創(chuàng)建頂點(diǎn)著色器
    vertexShader = LoadShader(GL_VERTEX_SHADER, vertexShaderCode);
    //創(chuàng)建片元著色器
    fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fragmentShaderCode);
    //將頂點(diǎn)著色器和片元著色器交給統(tǒng)一程序管理
    mProgram = linkProgram(vertexShader, fragmentShader);
}

/**圖形尺寸
 *
 * @param env
 * @param obj
 * @param width
 * @param height
*/
glm::mat4 mProjectionMatrix;
glm::mat4 mViewMatrix;
glm::mat4 mMVPMatrix;
float mMVPMatrixArray[16];

JNIEXPORT void JNICALL surfaceChanged(JNIEnv *env, jobject obj, jint width, jint height) {
    //設(shè)置視口
    glViewport(0, 0, width, height);
    //寬高比
    float ratio = (float) width / height;
    //正交投影矩陣
    mProjectionMatrix = glm::ortho(-ratio, ratio, -1.0f, 1.0f, 0.0f,
                                   100.0f); //ratio 一般表示視口的寬高比,width/height
    //透視投影矩陣
//    glm::mat4 Projection = glm::perspective(45.0f, ratio, 0.1f, 100.f); //ratio 一般表示視口的寬高比,width/height
    //相機(jī)位置
    mViewMatrix = glm::lookAt(glm::vec3(1, 1, 0.7), // 相機(jī)位置
                              glm::vec3(0, 0, 0), // 觀察點(diǎn)坐標(biāo)
                              glm::vec3(0, 0, 1));
    //矩陣合并
    mMVPMatrix = mProjectionMatrix * mViewMatrix;
    //矩陣轉(zhuǎn)換成數(shù)組
    int m = 0;
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++) {
            mMVPMatrixArray[m] = mMVPMatrix[i][j];
            m++;
        }
}


/**渲染繪制
 *
 * @param env
 * @param obj
*/
JNIEXPORT void JNICALL drawFrame(JNIEnv *env, jobject obj) {
    //清除顏色緩沖區(qū)
    glClear(GL_COLOR_BUFFER_BIT);
    //使用程序
    glUseProgram(mProgram);
    //獲取變換矩陣vMatrix成員句柄
    GLint mMatrixHandler = glGetUniformLocation(mProgram, "vMatrix");
    //指定vMatrix的值
    glUniformMatrix4fv(mMatrixHandler, 1, false, mMVPMatrixArray);
    //獲取頂點(diǎn)著色器的vPosition成員句柄
    GLint mPositionHandle = glGetAttribLocation(mProgram, "vPosition");
    //啟用圖形頂點(diǎn)的句柄
    glEnableVertexAttribArray(mPositionHandle);
    //準(zhǔn)備圖形的坐標(biāo)數(shù)據(jù)
    glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GL_FLOAT, GL_FALSE, vertexStride,
                          vertexPoints);
    //獲取片元著色器的vColor成員的句柄
    GLint mColorHandle = glGetUniformLocation(mProgram, "vColor");
    //設(shè)置繪制圖形的顏色
    glUniform4fv(mColorHandle, 1, color);
    //繪制圖形
    glLineWidth(3.0f);
    glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
    //禁止頂點(diǎn)數(shù)組的句柄
    glDisableVertexAttribArray(mPositionHandle);
}


/**加載著色器
 *
 */
JNIEXPORT GLuint LoadShader(int type, char *shaderCode) {
    //創(chuàng)建一個(gè)著色器
    GLuint shader = glCreateShader(type);
    if (shader != 0) {
        //加載到著色器
        glShaderSource(shader, 1, &shaderCode, NULL);
        //編譯著色器
        glCompileShader(shader);
        //檢測(cè)狀態(tài)
        GLint compileStatus;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
        if (compileStatus == 0) {
            //聲明log長度變量
            GLint infoLen = 0;
            //獲取長度并賦值
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen > 1) {
                //創(chuàng)建成功小于等于1
                char *infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
                glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
                printf("SHADER ERROR!");
                free(infoLog);
            }
            //創(chuàng)建失敗
            glDeleteShader(shader);
            return 0;
        }
        return shader;
    } else {
        //創(chuàng)建失敗
        return 0;
    }
}

/**鏈接著色器
 *
 */
JNIEXPORT GLuint linkProgram(GLuint vertexShader, GLuint fragmentShader) {
    GLuint program = glCreateProgram();
    if (program != 0) {
        //將頂點(diǎn)著色器加入到程序
        glAttachShader(program, vertexShader);
        //將片元著色器加入到程序中
        glAttachShader(program, fragmentShader);
        //鏈接著色器程序
        glLinkProgram(program);
        //檢測(cè)狀態(tài)
        GLint linkStatus;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
        if (linkStatus == 0) {
            GLint infoLen = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen > 1) {
                char *infoLog = static_cast<char *>(malloc(sizeof(char) * infoLen));
                glGetProgramInfoLog(program, infoLen, NULL, infoLog);
                printf("PROGRAM ERROR!");
                free(infoLog);
            }
            glDeleteProgram(program);
            return 0;
        }
        return program;
    } else {
        //創(chuàng)建失敗
        return 0;
    }
}

/** 動(dòng)態(tài)注冊(cè)
* @param env
 * @return
*/
//本地方法聲明和具體邏輯連接
JNINativeMethod methods[] = {
        {"init", "()V",   (void *) init},
        {"surfaceCreated", "()V",   (void *) surfaceCreated},
        {"surfaceChanged", "(II)V", (void *) surfaceChanged},
        {"drawFrame",      "()V",   (void *) drawFrame}
};

/** 動(dòng)態(tài)注冊(cè)
* @param env
* @return
*/
jint registerNativeMethod(JNIEnv *env) {
    //到本地方法存在的類找出其方法聲明
    jclass cl = env->FindClass("com/example/openglndk/WaveRenderer");
    if ((env->RegisterNatives(cl, methods, sizeof(methods) / sizeof(methods[0]))) < 0) {
        return -1;
    }
    return 0;
}

/** 加載默認(rèn)回調(diào)
* @param vm
* @param reserved
* @return
*/
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    //注冊(cè)方法
    if (registerNativeMethod(env) != JNI_OK) {
        return -1;
    }
    return JNI_VERSION_1_6;
}

JAVA版本

  • Renderer類
package com.example.openglndk;

import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class MyRenderer implements GLSurfaceView.Renderer {
    /**
     * 坐標(biāo)個(gè)數(shù)(xyz)
     */
    private final static int COORDS_PER_VERTEX = 3;

    //頂點(diǎn)之間的偏移量
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)

    private float radius = 0.5f; //半徑
    private float height = 1.0f; //圓錐高度
    private int n = 360; //切割份數(shù)

    private FloatBuffer vertexBuffer;

    private int vertexShader;
    private int fragmentShader;
    private int mProgram;

    //聲明點(diǎn)坐標(biāo)
    private float vertexPoints[];
    //點(diǎn)的數(shù)量
    private int vertexCount;

    //設(shè)置顏色,依次為紅綠藍(lán)和透明通道
    //黑色
    private float color[] = {0.0f, 0.0f, 0.0f, 0.0f};

    //創(chuàng)建圓錐的所有點(diǎn)
    private float[] createPositions() {
        ArrayList<Float> data = new ArrayList<>();
        //錐上那個(gè)點(diǎn)
        data.add(0.0f);
        data.add(0.0f);
        data.add(height);        //給圓心相對(duì)圓邊增加高度,使之形成錐面
        //底部圓上點(diǎn)
        float angDegSpan = 360f / n;
        for (float i = 0; i < 360 + angDegSpan; i += angDegSpan) {
            data.add((float) (radius * Math.sin(i * Math.PI / 180f)));
            data.add((float) (radius * Math.cos(i * Math.PI / 180f)));
            data.add(0.0f);
        }
        float[] f = new float[data.size()];    //所有的頂點(diǎn)
        for (int i = 0; i < f.length; i++) {
            f[i] = data.get(i);
        }
        return f;
    }

    private final String vertexShaderCode =
            "attribute vec4 vPosition;" +
                    "uniform mat4 vMatrix;" +
                    "void main() {" +
                    "  gl_Position = vMatrix*vPosition;" +
                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";

    public MyRenderer() {
        vertexPoints = createPositions();
        vertexCount = vertexPoints.length / COORDS_PER_VERTEX;
        //坐標(biāo)
        vertexBuffer = ByteBuffer.allocateDirect(
                vertexPoints.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        vertexBuffer.put(vertexPoints);
        vertexBuffer.position(0);
    }

    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
        //設(shè)置背景為白色
        GLES30.glClearColor(1, 1, 1, 1);
        vertexShader = LoadShader(GLES30.GL_VERTEX_SHADER,
                vertexShaderCode);
        fragmentShader = LoadShader(GLES30.GL_FRAGMENT_SHADER,
                fragmentShaderCode);
        mProgram = linkProgram(vertexShader, fragmentShader);
    }


    private float mProjectionMatrix[] = new float[16];
    private float mViewMatrix[] = new float[16];
    private float mMVPMatrix[] = new float[16];

    @Override
    public void onSurfaceChanged(GL10 gl10, int width, int height) {
        GLES30.glViewport(0, 0, width, height);
        //寬高比
        float ratio = (float) width / height;
        //設(shè)置投影矩陣
        Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
        //設(shè)置相機(jī)角度(核心)
        Matrix.setLookAtM(mViewMatrix, 0, 1, -3, -1, 0f, 0f, 0f, 0f, 0.0f, 1.0f);
        //矩陣合并
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
    }

    //每20ms刷新
    @Override
    public void onDrawFrame(GL10 gl10) {
        //清除顏色緩沖區(qū)
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
        //將程序加入
        GLES30.glUseProgram(mProgram);
        //獲取變換矩陣vMatrix成員句柄
        //圖形參數(shù)
        int mMatrixHandler = GLES30.glGetUniformLocation(mProgram, "vMatrix");
        //指定vMatrix的值
        GLES30.glUniformMatrix4fv(mMatrixHandler, 1, false, mMVPMatrix, 0);
        //獲取頂點(diǎn)著色器的vPosition成員句柄
        int mPositionHandle = GLES30.glGetAttribLocation(mProgram, "vPosition");
        //啟用頂點(diǎn)的句柄
        GLES30.glEnableVertexAttribArray(mPositionHandle);
        //準(zhǔn)備坐標(biāo)數(shù)據(jù)
        GLES30.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                GLES30.GL_FLOAT, false,
                vertexStride, vertexBuffer);
        //獲取片元著色器的vColor成員的句柄
        int mColorHandle = GLES30.glGetUniformLocation(mProgram, "vColor");
        //設(shè)置圖形的顏色
        GLES30.glUniform4fv(mColorHandle, 1, color, 0);
        //繪制圖形
        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 0, vertexCount);
        //禁止頂點(diǎn)數(shù)組的句柄
        GLES30.glDisableVertexAttribArray(mPositionHandle);
    }

    /**
     * 編譯
     *
     * @param type       頂點(diǎn)著色器:GLES30.GL_VERTEX_SHADER
     *                   片段著色器:GLES30.GL_FRAGMENT_SHADER
     * @param shaderCode
     * @return
     */
    private static int LoadShader(int type, String shaderCode) {
        //創(chuàng)建一個(gè)著色器
        final int shaderId = GLES30.glCreateShader(type);
        if (shaderId != 0) {
            //加載到著色器
            GLES30.glShaderSource(shaderId, shaderCode);
            //編譯著色器
            GLES30.glCompileShader(shaderId);
            //檢測(cè)狀態(tài)
            final int[] compileStatus = new int[1];
            GLES30.glGetShaderiv(shaderId, GLES30.GL_COMPILE_STATUS, compileStatus, 0);
            if (compileStatus[0] == 0) {
                String logInfo = GLES30.glGetShaderInfoLog(shaderId);
                System.err.println(logInfo);
                //創(chuàng)建失敗
                GLES30.glDeleteShader(shaderId);
                return 0;
            }
            return shaderId;
        } else {
            //創(chuàng)建失敗
            return 0;
        }
    }

    /**
     * 鏈接小程序
     *
     * @param vertexShaderId   頂點(diǎn)著色器
     * @param fragmentShaderId 片段著色器
     * @return
     */
    public static int linkProgram(int vertexShaderId, int fragmentShaderId) {
        final int programId = GLES30.glCreateProgram();
        if (programId != 0) {
            //將頂點(diǎn)著色器加入到程序
            GLES30.glAttachShader(programId, vertexShaderId);
            //將片元著色器加入到程序中
            GLES30.glAttachShader(programId, fragmentShaderId);
            //鏈接著色器程序
            GLES30.glLinkProgram(programId);
            final int[] linkStatus = new int[1];
            GLES30.glGetProgramiv(programId, GLES30.GL_LINK_STATUS, linkStatus, 0);
            if (linkStatus[0] == 0) {
                String logInfo = GLES30.glGetProgramInfoLog(programId);
                System.err.println(logInfo);
                GLES30.glDeleteProgram(programId);
                return 0;
            }
            return programId;
        } else {
            //創(chuàng)建失敗
            return 0;
        }
    }
}

到了這里,關(guān)于【OpenGL ES】三維圖形繪制的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 積跬步至千里 || PyTorch 中 shape 和 size 屬性的區(qū)別

    在深度學(xué)習(xí)中,張量 Tensor 和 向量 array 有相似之處,不同的在于 Tensor 兼具了求導(dǎo)的屬性。張量和向量一樣,可以表示多維矩陣,也同樣都有 shape 和 size 屬性。 PyTorch 中 shape 可以計(jì)算出各個(gè)維數(shù)的個(gè)數(shù),即表示多維矩陣的形狀; PyTorch 中 size() 可通過參數(shù)計(jì)算出特定維度上的

    2024年02月12日
    瀏覽(19)
  • 積跬步至千里 || PyTorch 中的“with torch no_grad” 語句

    “with ”torch.no_grad()的使用就像一個(gè)循環(huán),其中循環(huán)內(nèi)的每個(gè)張量都將requires_grad設(shè)置為False。這意味著當(dāng)前與當(dāng)前計(jì)算圖相連的任何具有梯度的張量現(xiàn)在都與當(dāng)前圖分離。我們不再能夠計(jì)算關(guān)于這個(gè)張量的梯度。 張量從當(dāng)前圖中分離,直到它在循環(huán)內(nèi)。一旦它離開循環(huán),如果

    2024年02月11日
    瀏覽(20)
  • MATLAB 之 繪制三維圖形的基本函數(shù)、三維曲面和其他三維圖形

    MATLAB 之 繪制三維圖形的基本函數(shù)、三維曲面和其他三維圖形

    三維圖形具有更強(qiáng)的數(shù)據(jù)表現(xiàn)能力,為此 MATLAB 提供了豐富的函數(shù)來繪制三維圖形。繪制三維圖形與繪制二維圖形的方法十分類似,很多都是在二維繪圖的基礎(chǔ)上擴(kuò)展而來。 基本的三維圖形函數(shù)為 plot3 ,它是將二維繪圖函數(shù) plot 的有關(guān)功能擴(kuò)展到三維空間,用來繪制三維曲線

    2024年02月06日
    瀏覽(30)
  • 計(jì)算機(jī)圖形學(xué)實(shí)驗(yàn)四 OpenGL的鼠標(biāo)交互繪制

    一、實(shí)驗(yàn)?zāi)康?1.掌握OpenGL的鼠標(biāo)按鈕響應(yīng)函數(shù)。 2.掌握OpenGL的鼠標(biāo)移動(dòng)響應(yīng)函數(shù)。 3.進(jìn)一步鞏固OpenGL的基本圖元繪制基礎(chǔ)。 二、實(shí)驗(yàn)內(nèi)容 1.鼠標(biāo)畫草圖——實(shí)現(xiàn)鼠標(biāo)點(diǎn)到哪,線就畫到哪。 思路: 1)在主程序注冊(cè)鼠標(biāo)響應(yīng)和鼠標(biāo)移動(dòng)子函數(shù): glutMouseFunc(mymouse); glutMotionFunc(mym

    2023年04月20日
    瀏覽(104)
  • 【小沐學(xué)GIS】基于C#繪制三維數(shù)字地球Earth(OpenGL)

    【小沐學(xué)GIS】基于C#繪制三維數(shù)字地球Earth(OpenGL)

    ??三維數(shù)字地球系列相關(guān)文章如下??: 1 【小沐學(xué)GIS】基于C++繪制三維數(shù)字地球Earth(OpenGL、glfw、glut)第一期 2 【小沐學(xué)GIS】基于C++繪制三維數(shù)字地球Earth(OpenGL、glfw、glut)第二期 3 【小沐學(xué)GIS】基于OpenSceneGraph(OSG)繪制三維數(shù)字地球Earth 4 【小沐學(xué)GIS】基于C++繪制太陽系

    2024年01月22日
    瀏覽(18)
  • 【GIS開發(fā)】基于C++繪制三維數(shù)字地球Earth(OpenGL、glfw、glut)

    【GIS開發(fā)】基于C++繪制三維數(shù)字地球Earth(OpenGL、glfw、glut)

    ??三維數(shù)字地球系列相關(guān)文章如下??: 1 【小沐學(xué)GIS】基于C++繪制三維數(shù)字地球Earth(OpenGL、glfw、glut)第一期 2 【小沐學(xué)GIS】基于C++繪制三維數(shù)字地球Earth(OpenGL、glfw、glut)第二期 3 【小沐學(xué)GIS】基于OpenSceneGraph(OSG)繪制三維數(shù)字地球Earth 4 【小沐學(xué)GIS】基于C++繪制太陽系

    2023年04月17日
    瀏覽(56)
  • OpenGL ES 繪制一張圖片

    OpenGL ES 繪制一張圖片

    GLSL 的修飾符與數(shù)據(jù)類型 GLSL 中變量的修飾符 const:修飾不可被外界改變的常量 attribute:修飾經(jīng)常更改的變量,只可以在頂點(diǎn)著色器中使用 uniform:修飾不經(jīng)常更改的變量,可用于頂點(diǎn)著色器和片段著色器 varying:修飾在頂點(diǎn)著色器計(jì)算,然后傳遞到片元著色器中使用的變量

    2024年02月06日
    瀏覽(15)
  • c++中用opengl的gl函數(shù)在三維空間中繪制圓形和畫球體

    c++中用opengl的gl函數(shù)在三維空間中繪制圓形和畫球體

    繪制圓形原理: 畫圓形的原理如下圖,畫一個(gè)圓形就相當(dāng)于切蛋糕一樣,將一個(gè)圓形切成很多個(gè)扇形,而扇形可以用三角形類似表示,所以我們可以將繪制圓形轉(zhuǎn)化為繪制許多個(gè)三角形。 繪制圓形的代碼如下: 繪制球體原理: 數(shù)學(xué)中的簡單原理,一個(gè)球體相當(dāng)于一個(gè)圓形繞

    2024年02月11日
    瀏覽(14)
  • OpenGL ES入門教程(二)之繪制一個(gè)平面桌子

    OpenGL ES入門教程(二)之繪制一個(gè)平面桌子

    上一篇文章OpenGL ES入門教程(一)編寫第一個(gè)OpenGL程序,我們創(chuàng)建了自己的第一個(gè)OpenGL程序,實(shí)現(xiàn)了繪制紅色背景的Activity頁面,算是OpenGL ES的hello world程序吧。本篇文章基于上一篇文章基礎(chǔ)上講解如何使用OpenGL繪制一張平面桌子,桌子由一個(gè)長方形構(gòu)成,且長方形中間繪制一

    2024年01月17日
    瀏覽(19)
  • LearnOpenGL - Android OpenGL ES 3.0 繪制三角形

    LearnOpenGL - Android OpenGL ES 3.0 繪制三角形

    LearnOpenGL 筆記 - 入門 01 OpenGL LearnOpenGL 筆記 - 入門 02 創(chuàng)建窗口 LearnOpenGL 筆記 - 入門 03 你好,窗口 LearnOpenGL 筆記 - 入門 04 你好,三角形 OpenGL - 如何理解 VAO 與 VBO 之間的關(guān)系 經(jīng)過一段時(shí)間 OpenGL 的學(xué)習(xí),我們已經(jīng)掌握了如何使用 glwf 在桌面端繪制簡單圖形?,F(xiàn)在讓我們把目光

    2024年02月12日
    瀏覽(47)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包