opengl es3.0学习篇三:简单写一个三角形展现

资料来源:java

OpenGL ES 2 for Android —a Quick-Start Guideandroid

https://developer.android.com/guide/topics/graphics/openglgit

本章文章只是简单的画一个三角形到手机端中,比较简单,直接看着官网资料就能写出来,下面是代码:github

Manifest中声明使用的opengl es版本:缓存

<uses-feature android:glEsVersion="0x00030000" android:required="true" />

xml中直接声明一个全屏的GLSurfaceView,这里不就贴了。ide

在MainActivity中:ui

private GLSurfaceView mSurfaceView;

    @Override
    protected void onPause() {
        super.onPause();
        if (mSurfaceView != null) {
            mSurfaceView.onPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mSurfaceView != null) {
            mSurfaceView.onResume();
        }
    }
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intGL();
    }

    private void intGL() {
        mSurfaceView = findViewById(R.id.gl);

        mSurfaceView.setEGLContextClientVersion(3);
        mSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
        mSurfaceView.setRenderer(new MyRenderer());
        //RenderMode 有两种,RENDERMODE_WHEN_DIRTY 和 RENDERMODE_CONTINUOUSLY,
        // 前者是懒惰渲染,须要手动调用 glSurfaceView.requestRender() 才会进行更新,然后者则是不停渲染。
        mSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }


    private static class MyRenderer implements GLSurfaceView.Renderer {
        private Triangle mSquare;

        @Override
        public void onSurfaceCreated(GL10 unused, EGLConfig config) {
            mSquare = new Triangle();
        }

        @Override
        public void onSurfaceChanged(GL10 unused, int width, int height) {
            //设置 Screen space 的大小
            GLES30.glViewport(0, 0, width, height);
        }

        //绘制的过程其实就是为 shader 代码变量赋值,并调用绘制命令的过程
        @Override
        public void onDrawFrame(GL10 unused) {
            mSquare.onDraw();
        }
    }

Triangle文件:this

public class Triangle {
    private FloatBuffer vertexBuffer;
    private final String vertexShaderCode =
            "#version 300 es  \n" +
                    "layout(location = 0) in vec4 vPosition;\n" +
                    "layout(location = 1) in vec4 aColor;\n"+
                    "out vec4 vColor;"+
                    "void main() {\n" +
                    "gl_Position = vPosition;\n" +
                    "vColor=aColor;\n" +
                    "}";

    private final String fragmentShaderCode =
            "#version 300 es  \n" +
                    "precision mediump float;\n" +
                    "out vec4 fragColor;\n" +
                    "in vec4 vColor;" +
                    "void main() {\n" +
                    "fragColor = vColor;\n" +
                    "}";
    // number of coordinates per vertex in this array
    static final int COORDS_PER_VERTEX = 3;
    static float triangleCoords[] = {   // in counterclockwise order:
            0.0f,  0.622008459f, 0.0f, // top
            -0.5f, -0.311004243f, 0.0f, // bottom left
            0.5f, -0.311004243f, 0.0f  // bottom right
    };
    private final int mProgram;
    // Set color with red, green, blue and alpha (opacity) values
    float color[] = { 1.0f,0.0f,0.0f, 1.0f };
    public static int loadShader(int type, String shaderCode){

        // create a vertex shader type (GLES30.GL_VERTEX_SHADER)
        // or a fragment shader type (GLES30.GL_FRAGMENT_SHADER)
        int shader = GLES30.glCreateShader(type);

        // add the source code to the shader and compile it
        GLES30.glShaderSource(shader, shaderCode);
        GLES30.glCompileShader(shader);

        return shader;
    }
    public Triangle() {
        // initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (number of coordinate values * 4 bytes per float)
                triangleCoords.length * 4);
        // use the device hardware's native byte order
        bb.order(ByteOrder.nativeOrder());

        // create a floating point buffer from the ByteBuffer
        vertexBuffer = bb.asFloatBuffer();
        // add the coordinates to the FloatBuffer
        vertexBuffer.put(triangleCoords);
        // set the buffer to read the first coordinate
        vertexBuffer.position(0);
        int vertexShader = loadShader(GLES30.GL_VERTEX_SHADER,
                vertexShaderCode);
        int fragmentShader = loadShader(GLES30.GL_FRAGMENT_SHADER,
                fragmentShaderCode);

        // create empty OpenGL ES Program
        mProgram = GLES30.glCreateProgram();

        // add the vertex shader to program
        GLES30.glAttachShader(mProgram, vertexShader);

        // add the fragment shader to program
        GLES30.glAttachShader(mProgram, fragmentShader);

        // creates OpenGL ES program executables
        GLES30.glLinkProgram(mProgram);
    }
    private int mPositionHandle;
    private int mColorHandle;

    private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
    public void onDraw(){
        // Add program to OpenGL ES environment
        GLES30.glUseProgram(mProgram);

        // get handle to vertex shader's vPosition member
        mPositionHandle = GLES30.glGetAttribLocation(mProgram, "vPosition");
        // Enable a handle to the triangle vertices
        GLES30.glEnableVertexAttribArray(mPositionHandle);
        // Prepare the triangle coordinate data
        GLES30.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                GLES30.GL_FLOAT, false,
                vertexStride, vertexBuffer);

        // get handle to fragment shader's vColor member
        mColorHandle = GLES30.glGetAttribLocation(mProgram, "aColor");

        // Set color for drawing the triangle
        GLES30.glVertexAttrib4fv(mColorHandle,  color, 0);

        // Draw the triangle
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vertexCount);

        // Disable vertex array
        GLES30.glDisableVertexAttribArray(mPositionHandle);
    }
}

这样就会在GlSurfaceView当中绘制出一个三角形了。spa

这里顺便记录一下对应的glVertexAttrib4fv()glUniform4fv()的区别:.net

private final String vertexShaderCode =
            "#version 300 es  \n" +
                    "layout(location = 0) in vec4 vPosition;\n" +
                    "layout(location = 1) in vec4 aColor;\n"+ //和下面代码的区别
                    "out vec4 vColor;"+
                    "void main() {\n" +
                    "gl_Position = vPosition;\n" +
                    "vColor=aColor;\n" +
                    "}";

    private final String fragmentShaderCode =
            "#version 300 es  \n" +
                    "precision mediump float;\n" +
                    "out vec4 fragColor;\n" +
                    "in vec4 vColor;" +
                    "void main() {\n" +
                    "fragColor = vColor;\n" +
                    "}";
...
  // get handle to fragment shader's vColor member
        mColorHandle = GLES30.glGetAttribLocation(mProgram, "aColor");

        // Set color for drawing the triangle
        GLES30.glVertexAttrib4fv(mColorHandle,  color, 0);

上述代码中在glsl语言中使用了in vec4 aColor;说明这个变量经由外部传递,是个可变的参数(即咱们在第一次刷新能够设置为红色,第二次刷新能够改变成蓝色),使用的方法则是经过glVertexAttrib4fv()或者glVertexAttrib4f()来进行传递 ,而若是使用了底下的代码的话:

private final String vertexShaderCode =
            "#version 300 es  \n" +
                    "layout(location = 0) in vec4 vPosition;\n" +
                    "void main() {\n" +
                    "gl_Position = vPosition;\n" +
                    "}";

    private final String fragmentShaderCode =
            "#version 300 es  \n" +
                    "precision mediump float;\n" +
                    "out vec4 fragColor;\n" +
                    "uniform vec4 vColor;\n"+ //区别
                    "void main() {\n" +
                    "fragColor = vColor;\n" +
                    "}";
					....
        mColorHandle = GLES30.glGetUniformLocation(mProgram, "vColor");
        // Set color for drawing the triangle
//        GLES30.glVertexAttrib4fv(mColorHandle,  color, 0);
        GLES30.glUniform4fv(mColorHandle, 1, color, 0);

那么永远都只会是一种颜色,由于uniform设置至关于java里的final和c中的const,即常量的概念。

若是讲的不太清楚,引用一下大牛的博客(基于opengl es2.0,3.0中使用in类型来表明attribute):

attribute(属性)变量和uniform变量的不一样之处在于attribute 变量中包含顶点的具体数据,当每次执行shader调用时会从顶点缓存中从新加载一个新的值。而uniform类型的变量在整个绘制调用中始终使用同一个变量。这意味着你在绘制调用前加载的值在每一个vertex shader调用时能访问到相同的值。uniform变量在存储光照参数(光照位置、方向等)、变换矩阵、纹理对象句柄等这一类型的数据时很是有用。

来源:https://blog.csdn.net/Rongbo_J/article/details/45112187

效果图:

opengl_demo

代码连接:

https://github.com/JerryChan123/LearnOEL/tree/gl30

相关文章
相关标签/搜索