当前位置:必发365电子游戏 > 编程 > 必发365电子游戏眼下最全的Android OpenGL文书档案
必发365电子游戏眼下最全的Android OpenGL文书档案
2019-12-19

Android 3D 游戏开荒教程

#include"stdafx.h"
#define GLUT_DISABLE_ATEXIT_HACK  
#include <GL/glut.h>
//glut自动将gl.h和glu.h包含了
#include"math.h"
#include <time.h>

const int n = 20; 
const GLfloat R = 20.0f; 
const GLfloat Pi = 3.1415926536f;
// 太阳、地球和月亮 
// 假设每个月都是30天 
// 一年12个月,共是360天 
static int day = 200; // day的变化:从0到359

#define WIDTH 400 
#define HEIGHT 400 
static GLfloat angle = 0.0f;

#define ColoredVertex(c, v) do{ glColor3fv(c); glVertex3fv(v); }while(0)

void myDisplay5(void) 
{ 
    static int list = 0; 
    if( list == 0 ) 
    {
        // 如果显示列表不存在,则创建 
        /* GLfloat PointA[] = {-0.5, -5*sqrt(5)/48, sqrt(3)/6}, 
                   PointB[] = { 0.5, -5*sqrt(5)/48, sqrt(3)/6}, 
                   PointC[] = { 0, -5*sqrt(5)/48, -sqrt(3)/3}, 
                   PointD[] = { 0, 11*sqrt(6)/48, 0}; 
                   */ 
        // 2007年4月27日修改 
        GLfloat PointA[] = { 0.5f, -sqrt(6.0f)/12, -sqrt(3.0f)/6}, 
                PointB[] = {-0.5f, -sqrt(6.0f)/12, -sqrt(3.0f)/6},
                PointC[] = { 0.0f, -sqrt(6.0f)/12, sqrt(3.0f)/3},
                PointD[] = { 0.0f, sqrt(6.0f)/4, 0}; 

        GLfloat ColorR[] = {1, 0, 0}, 
                ColorG[] = {0, 1, 0}, 
                ColorB[] = {0, 0, 1}, 
                ColorY[] = {1, 1, 0};
        //一、分配显示列表编号
        //要分配i个连续的未使用的显示列表编号,返回的是分配的若干连续编号中最小的一个。
        //。如果函数返回零,表示分配失败。
        list = glGenLists(1); 

        //二、创建显示列表
        //glNewList有两个参数,
        //第一个参数是一个正整数表示装入到哪个显示列表。
        //第二个参数有两种取值,如果为GL_COMPILE,则表示以下的内容只是装入到显示列表,但现在不执行它们;
        //如果为GL_COMPILE_AND_EXECUTE,表示在装入的同时,把装入的内容执行一遍。
        glNewList(list, GL_COMPILE); 
        //显示列表只能装入OpenGL函数,而不能装入其它内容
        glBegin(GL_TRIANGLES); 
        // 平面ABC 
        ColoredVertex(ColorR, PointA); 
        ColoredVertex(ColorG, PointB); 
        ColoredVertex(ColorB, PointC);
        // 平面ACD 
        ColoredVertex(ColorR, PointA); 
        ColoredVertex(ColorB, PointC);
        ColoredVertex(ColorY, PointD); 
        // 平面CBD 
        ColoredVertex(ColorB, PointC); 
        ColoredVertex(ColorG, PointB);
        ColoredVertex(ColorY, PointD); 
        // 平面BAD 
        ColoredVertex(ColorG, PointB);
        ColoredVertex(ColorR, PointA);
        ColoredVertex(ColorY, PointD); 
        glEnd(); 
        glEndList(); 
        glEnable(GL_DEPTH_TEST);
        } 
        // 已经创建了显示列表,在每次绘制正四面体时将调用它 
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glPushMatrix(); 
        glRotatef(angle, 1, 0.5, 0); 

        //三、调用显示列表
        //使用glCallList函数可以调用一个显示列表。该函数有一个参数,表示要调用的显示列表的编号。
        glCallList(list); 
        glPopMatrix(); 

        //
        //使用glDeleteLists来销毁一串编号连续的显示列表。
        glutSwapBuffers();
}
void myIdle2(void) 
{ 
    ++angle; 
    if( angle >= 360.0f ) 
        angle = 0.0f; 
    myDisplay5(); 
}

void myDisplay4(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    // 创建透视效果视图 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    //透视投影
    gluPerspective(90.0f, 1.0f, 1.0f, 20.0f); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(0.0, 5.0, -10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 
    // 定义太阳光源,它是一种白色的光源 
    { 
        GLfloat sun_light_position[] = {0.0f, 0.0f, 0.0f, 1.0f};
        GLfloat sun_light_ambient[] = {0.0f, 0.0f, 0.0f, 1.0f};
        GLfloat sun_light_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; 
        GLfloat sun_light_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
        glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position); 
        glLightfv(GL_LIGHT0, GL_AMBIENT, sun_light_ambient); 
        glLightfv(GL_LIGHT0, GL_DIFFUSE, sun_light_diffuse); 
        glLightfv(GL_LIGHT0, GL_SPECULAR, sun_light_specular); 
        glEnable(GL_LIGHT0); 
        glEnable(GL_LIGHTING); 
        glEnable(GL_DEPTH_TEST);
    }
    // 定义太阳的材质并绘制太阳 
    { 
        GLfloat sun_mat_ambient[] = {0.0f, 0.0f, 0.0f, 1.0f}; 
        GLfloat sun_mat_diffuse[] = {0.0f, 0.0f, 0.0f, 1.0f}; 
        GLfloat sun_mat_specular[] = {0.0f, 0.0f, 0.0f, 1.0f}; 
        GLfloat sun_mat_emission[] = {0.5f, 0.0f, 0.0f, 1.0f}; 
        GLfloat sun_mat_shininess = 0.0f; 
        glMaterialfv(GL_FRONT, GL_AMBIENT, sun_mat_ambient); 
        glMaterialfv(GL_FRONT, GL_DIFFUSE, sun_mat_diffuse); 
        glMaterialfv(GL_FRONT, GL_SPECULAR, sun_mat_specular); 
        glMaterialfv(GL_FRONT, GL_EMISSION, sun_mat_emission); 
        glMaterialf (GL_FRONT, GL_SHININESS, sun_mat_shininess); 
        glutSolidSphere(2.0, 40, 32); 
    } 
    // 定义地球的材质并绘制地球 
    { 
        GLfloat earth_mat_ambient[] = {0.0f, 0.0f, 0.5f, 1.0f}; 
        GLfloat earth_mat_diffuse[] = {0.0f, 0.0f, 0.5f, 1.0f}; 
        GLfloat earth_mat_specular[] = {0.0f, 0.0f, 1.0f, 1.0f};
        GLfloat earth_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f}; 
        GLfloat earth_mat_shininess = 30.0f; 
        glMaterialfv(GL_FRONT, GL_AMBIENT, earth_mat_ambient); 
        glMaterialfv(GL_FRONT, GL_DIFFUSE, earth_mat_diffuse);
        glMaterialfv(GL_FRONT, GL_SPECULAR, earth_mat_specular); 
        glMaterialfv(GL_FRONT, GL_EMISSION, earth_mat_emission);
        glMaterialf (GL_FRONT, GL_SHININESS, earth_mat_shininess); 
        glRotatef(angle, 0.0f, -1.0f, 0.0f); 
        glTranslatef(5.0f, 0.0f, 0.0f); 
        glutSolidSphere(2.0, 40, 32); 
    } 
        glutSwapBuffers();

        //使用glLight*函数可设置光源的属性,使用glMaterial*函数可设置材质的属性,使用glLightModel*函数可设置光照模式。
}
double CalFrequency() 
{ 
    static int count; 
    static double save;
    static clock_t last, current; 
    double timegap; 
    ++count; 
    if( count <= 50 ) 
        return save; 
    count = 0; 
    last = current; 
    current = clock();
    timegap = (current-last)/(double)CLK_TCK; 
    save = 50.0/timegap; 
    return save;
}
void myDisplay2(void) 
{ 
    glEnable(GL_DEPTH_TEST); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(75, 1, 1, 400000000);
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(0, -200000000, 200000000, 0, 0, 0, 0, 0, 1);
    // 绘制红色的“太阳” 
    glColor3f(1.0f, 0.0f, 0.0f); 
    glutSolidSphere(69600000, 20, 20); 
    // 绘制蓝色的“地球” 
    glColor3f(0.0f, 0.0f, 1.0f); 
    glRotatef(day/360.0*360.0, 0.0f, 0.0f, -1.0f); 
    glTranslatef(150000000, 0.0f, 0.0f); 
    glutSolidSphere(15945000, 20, 20); 
    // 绘制黄色的“月亮” 
    glColor3f(1.0f, 1.0f, 0.0f); 
    glRotatef(day/30.0*360.0 - day/360.0*360.0, 0.0f, 0.0f, -1.0f); 
    glTranslatef(38000000, 0.0f, 0.0f); 
    glutSolidSphere(4345000, 20, 20); 

    glFlush();

    //小结:本课开始,我们正式进入了三维的OpenGL世界。
    //OpenGL通过矩阵变换来把三维物体转变为二维图象,进而在屏幕上显示出来。
    //为了指定当前操作的是何种矩阵,我们使用了函数glMatrixMode。 
    //我们可以移动、旋转观察点或者移动、旋转物体,使用的函数是glTranslate*和glRotate*。 
    //我们可以缩放物体,使用的函数是glScale*。 
    //我们可以定义可视空间,这个空间可以是“正投影”的(使用glOrtho或gluOrtho2D),
    //也可以是“透视投影”的(使用glFrustum或gluPerspective)。 
    //我们可以定义绘制到窗口的范围,使用的函数是glViewport。 
    //矩阵有自己的“堆栈”,方便进行保存和恢复。
    //这在绘制复杂图形时很有帮助。使用的函数是glPushMatrix和glPopMatrix。
}

void myDisplay3(void) 
{ 
    double FPS = CalFrequency();
    printf("FPS = %fn", FPS);
    glEnable(GL_DEPTH_TEST); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(75, 1, 1, 400000000);
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(0, -200000000, 200000000, 0, 0, 0, 0, 0, 1);
    // 绘制红色的“太阳” 
    glColor3f(1.0f, 0.0f, 0.0f); 
    glutSolidSphere(69600000, 20, 20); 
    // 绘制蓝色的“地球” 
    glColor3f(0.0f, 0.0f, 1.0f); 
    glRotatef(day/360.0*360.0, 0.0f, 0.0f, -1.0f); 
    glTranslatef(150000000, 0.0f, 0.0f); 
    glutSolidSphere(15945000, 20, 20); 
    // 绘制黄色的“月亮” 
    glColor3f(1.0f, 1.0f, 0.0f); 
    glRotatef(day/30.0*360.0 - day/360.0*360.0, 0.0f, 0.0f, -1.0f); 
    glTranslatef(38000000, 0.0f, 0.0f); 
    glutSolidSphere(4345000, 20, 20); 

    glFlush();
    glutSwapBuffers();

    //OpenGL动画和传统意义上的动画相似,都是把画面一幅一幅的呈现在观众面前。
    //一旦画面变换的速度快了,观众就会认为画面是连续的。 
    //双缓冲技术是一种在计算机图形中普遍采用的技术,绝大多数OpenGL实现都支持双缓冲技术。 
    //通常都是利用CPU空闲的时候绘制动画,但也可以有其它的选择。 
    //介绍了垂直同步的相关知识。 
    //介绍了一种简单的计算帧速(FPS)的方法。
}

void myIdle1(void) 
{ 
    /* 新的函数,在空闲时调用,作用是把日期往后移动一天并重新绘制,达到动画效果 */ 
    angle += 0.05f; 
    if( angle >= 360.0f ) 
        angle = 0.0f;
    myDisplay4(); 
}

void myIdle(void) 
{ 
    /* 新的函数,在空闲时调用,作用是把日期往后移动一天并重新绘制,达到动画效果 */ 
    ++day; 
    if( day >= 360 ) 
        day = 0; 
    myDisplay3(); 
}

//gl是基本函数库
//glu是gl的一些方便的和直观的高级应用
//这两个都和OS无关
//glut是和os打交道的库
//lut是一个系统无关的窗口系统,不用它就要用api或MFC画窗口,而glut窗口操作比较简单的,适合初学者或者编小型的程序
void init(void)
{
    glClearColor(1.0,1.0,1.0,0.0);
    //设置当前操作的矩阵
    glMatrixMode(GL_PROJECTION);

    //前把当前矩阵设置为单位矩阵。
    //glLoadIdentity();

    //将当前的可视空间设置为透视投影空间
    //glFrustum();

    //将当前的可视空间设置为正投影空间
    gluOrtho2D(0.0,200.0,0.0,150.0);

    //使用glViewport来定义视口

    //操作矩阵堆栈
    //当我们需要保存时,调用glPushMatrix函数。
    //当需要恢复最近一次的保存时,调用glPopMatrix函数。
}

void myDisplay(void) 
{ 
    double FPS = CalFrequency();
    printf("FPS = %fn", FPS);
    glClear(GL_COLOR_BUFFER_BIT); 
    glColor3f(1.0,0.0,0.0);

    glPolygonMode(GL_FRONT, GL_FILL); // 设置正面为填充模式 
    glPolygonMode(GL_BACK, GL_LINE); // 设置反面为线形模式 
    glFrontFace(GL_CCW); // 设置逆时针方向为正面 

    glBegin(GL_POLYGON); // 按逆时针绘制一个正方形,在左下方
    glVertex2f(-10.5f, -10.5f); 
    glVertex2f(10.0f, -10.5f); 
    glVertex2f(10.0f, 10.0f); 
    glVertex2f(-10.5f, 10.0f); 
    glEnd(); 

    glBegin(GL_POLYGON); // 按顺时针绘制一个正方形,在右上方 
    glVertex2f(10.0f, 10.0f); 
    glVertex2f(10.0f, 15.0f); 
    glVertex2f(15.0f, 15.0f); 
    glVertex2f(15.0f, 10.0f); 
    glEnd(); 

    glFlush(); 
}

void myDisplay1(void) 
{ 
    static GLubyte Mask[128]; 
    FILE *fp; 
    fp = fopen("11.bmp", "rb"); 
    if( !fp ) 
        exit(0); 
    if( fseek(fp, -(int)sizeof(Mask), SEEK_END) ) 
        exit(0); 
    if( !fread(Mask, sizeof(Mask), 1, fp) ) 
        exit(0); 
    fclose(fp); 

    glClear(GL_COLOR_BUFFER_BIT); 
    glColor3f(1.0,0.0,0.0);

    glEnable(GL_POLYGON_STIPPLE);
    glPolygonStipple(Mask); 
    glRectf(0.0f, 0.0f, 50.0f, 50.0f); 
    // 在左下方绘制一个有镂空效果的正方形 
    glDisable(GL_POLYGON_STIPPLE); 

    //glRectf(50.0f, 50.0f, 100.0f, 100.0f); 
    // 在右上方绘制一个无镂空效果的正方形 
    glFlush(); 
}

void lineSegment(void)
{
    //清除。GL_COLOR_BUFFER_BIT表示清除颜色
    glClear(GL_COLOR_BUFFER_BIT);

    //指定顶点颜色
    glColor3f(1.0,0.0,0.0);

    //使用glNormal*函数则可以指定法线向量

    //光源是通过glLight*函数来设置
    //,OpenGL至少会支持8个光源,即GL_LIGHT0到GL_LIGHT7
    //,glEnable(GL_LIGHT0);可以开启第0号光源。使用glDisable函数则可以关闭光源。
    //光源的属性GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR属性。这三个属性表示了光源所发出的光的反射特性(以及颜色)
    //GL_POSITION属性。表示光源所在的位置。
    //)GL_SPOT_DIRECTION、GL_SPOT_EXPONENT、GL_SPOT_CUTOFF属性。表示将光源作为聚光灯使用(这些属性只对位置性光源有效)

    //OpenGL默认是关闭光照处理的。
    //要打开光照处理功能,使用下面的语句: glEnable(GL_LIGHTING); 
    //要关闭光照处理功能,使用glDisable(GL_LIGHTING);即可。

    //材质则是通过glMaterial*函数来设置

    //glBegin支持参数
    //GL_POINTS点、GL_LINES线、
    //GL_LINE_STRIP不闭合多边形、
    //GL_LINE_LOOP闭合多边形、
    //GL_TRIANGLES三角形、
    //GL_TRIANGLE_STRIP、
    //GL_TRIANGLE_FAN
    //GL_POLYGON
    //GL_QUODS
    //GL_QUOD_STRIP

    //设置点的大小,单位为像素,默认为1.
    glPointSize(5.0f);
    glBegin(GL_POINTS); 
    glVertex2f(30.0f, 45.0f); 
    glVertex2f(78.0f, 54.0f); 
    glEnd();

    //设置线的宽度,与glPointSize用法类似
    glLineWidth(5.0f);
    //启动虚线模式
    glEnable(GL_LINE_STIPPLE);
    glLineStipple(2, 0x0F0F);
    glBegin(GL_LINES);
    glVertex2i(100,0);
    glVertex2i(0,50);
    glEnd();
    //关闭虚线模式
    glDisable(GL_LINE_STIPPLE);

    //可知坐标系原点在窗口的左下角
    int i; 
    int x = 100,y = 50;
    //glClear(GL_COLOR_BUFFER_BIT); 
    glBegin(GL_POLYGON); 
    for(i=0; i<n; ++i) 
        glVertex2f(x + R*cos(2*Pi/n*i),y + R*sin(2*Pi/n*i)); 
    glEnd();

    /*从三维的角度来看,一个多边形具有两个面。
    每一个面都可以设置不同的绘制方式:填充、只绘制边缘轮廓线、只绘制顶点,
    其中“填充”是默认的方式。可以为两个面分别设置不同的方式。*/ 

    //glPolygonMode(GL_FRONT, GL_FILL); 设置正面为填充方式 
    //glPolygonMode(GL_BACK, GL_LINE); 设置反面为边缘绘制方式 
    //glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); // 设置两面均为顶点绘制方式

    //一般约定为“顶点以逆时针顺序出现在屏幕上的面”为“正面”,另一个面即成为“反面”。
    //glFrontFace(GL_CCW); // 设置CCW方向为“正面”,CCW即CounterClockWise,逆时针 
    //glFrontFace(GL_CW); // 设置CW方向为“正面”,CW即ClockWise,顺时针

    //使用glEnable(GL_CULL_FACE);来启动剔除功能(使用glDisable(GL_CULL_FACE)可以关闭之)
    //使用glCullFace来进行剔除。参数可以是GL_FRONT,GL_BACK或者GL_FRONT_AND_BACK。

    //直线可以被画成虚线,而多边形则可以进行镂空。 
    //首先,使用glEnable(GL_POLYGON_STIPPLE);来启动镂空模式(使用glDisable(GL_POLYGON_STIPPLE)可以关闭之)。 
    //然后,使用glPolygonStipple来设置镂空的样式。

    //保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待)。其作用跟fflush(stdout)类似。
    glFlush();
}

//argc 是指命令行输入参数的个数(以空白符分隔) argv存储了所有的命令行参数 
int main(int argc, char **argv)
{    
    //以glut 开头的函数都是GLUT工具包所提供的函数

    //对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次。
    glutInit(&argc,argv);

    //设置显示方式
    //GLUT_RGB表示使用RGB颜色,GLUT_INDEX表示使用索引颜色
    //GLUT_SINGLE表示使用单缓冲,GLUT_DOUBLE使用双缓冲
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);

    //设置窗口在屏幕中的位置
    glutInitWindowPosition(100,100);

    //设置窗口的大小
    glutInitWindowSize(WIDTH,HEIGHT);

    //根据前面设置的信息创建窗口。参数将被作为窗口的标题。注意:窗口被创建后,并不立即显示到屏幕上。需要调用glutMainLoop才能看到窗口
    glutCreateWindow("测试");

    init();

    //设置一个函数,当需要进行画图时,这个函数就会被调用
    glutDisplayFunc(myDisplay4);

    glutIdleFunc(&myIdle1); // 新加入了这句,空闲时调用,实现动画效果

    glutMainLoop();

    return 0;
}

(Open Graphics Library)

 

时下最全的Android OpenGL文书档案

这几篇Android 3D游戏开辟的篇章原来的书文出自一个人西班牙人Martin在droidnova.com写的稿子,由lixinso翻译为汉语。

拷贝于博客:
首先部分首先介绍OpenGL相关的术语,并指引您最早3D开垦的率先步。
那么些关于3D游戏的多重的名称为 Vortex .
那些科目首要focus在3D编制程序上,其余的东西举例菜单和顺序生命周期纵然是代码的黄金年代部分,不过在这里边不会被提到。
第一同始介绍OpenGL的术语。
顶点Vertex
终端是3D空间中的三个点,也是超多对象的根底成分。在OpenGL中您能够生命少至二维坐标(X,Y卡塔尔(قطر‎,多至四维(X,Y,Z,W卡塔尔(英语:State of Qatar). w轴是可选的,暗中认可的值是1.0. Z轴也是可选的,默感觉0. 在这里个种类中,大家就要用到3个至关心重视要的坐标X,Y,Z,因为W经常都是被用来作为占位符。vertex的复数是vertices(那对非英语母语的人的话相当主要,因为那便于发生歧义)。全数的指标都以用vertices作为它们的点,因为点正是vertex。
三角形Triangle
三角形供给八个点才干制造。因而在OpenGL中,大家使用3个尖峰来创设八个三角。
多边形Polygon
多方形是最少有3个延续着的点组成的几个对象。三角形也是三个多边形。
图元Primitives
二个Primitive是叁个三个维度的靶子,使用三角形也许多方形创立。形象的说,一个有50000个极点的不胜精美的模子是三个Primitive,相似多少个唯有500个极端的低模也称之为三个Primitive。
到现在我们能够起来形成了。
成立三个工程交Vortex,activity也是以此名字。大家的工程应该大概是这些样子的:

package com.droidnova.android.games.vortex;

import android.app.Activity;

import android.os.Bundle;

 

public class Vortex extends Activity {

    private static final String LOG_TAG = Vortex.class.getSimpleName();

    private VortexView _vortexView;

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        _vortexView = new VortexView(this);

        setContentView(_vortexView);

    }

}

如上海体育地方所示,大家早就增多了View。让我们看一下VortexView类。

package com.droidnova.android.games.vortex;

 

import android.content.Context;

import android.opengl.GLSurfaceView;

 

public class VortexView extends GLSurfaceView {

    private static final String LOG_TAG = VortexView.class.getSimpleName();

    private VortexRenderer _renderer;

 

    public VortexView(Context context) {

        super(context);

        _renderer = new VortexRenderer();

        setRenderer(_renderer);

    }

}

如上所示,大家继续了GLSurfaceView是因为它会协理大家画3D图像。接下来看VortexRenderer类。三个Renderer包罗画生龙活虎帧所必备的装有东西。 援用自那儿references 。Renderer负责OpenGL call来render一个帧。
来看一下那一个类:

package com.droidnova.android.games.vortex;

 

import javax.microedition.khronos.egl.EGLConfig;

import javax.microedition.khronos.opengles.GL10;

 

import android.opengl.GLSurfaceView;

 

public class VortexRenderer implements GLSurfaceView.Renderer {

private static final String LOG_TAG = VortexRenderer.class.getSimpleName();

 

private float _red = 0.9f;

private float _green = 0.2f;

private float _blue = 0.2f;

 

@Override

public void onSurfaceCreated(GL10 gl, EGLConfig config) {

// Do nothing special.

}

 

@Override

public void onSurfaceChanged(GL10 gl, int w, int h) {

gl.glViewport(0, 0, w, h);

}

 

@Override

public void onDrawFrame(GL10 gl) {

// define the color we want to be displayed as the "clipping wall"

gl.glClearColor(_red, _green, _blue, 1.0f);

// clear the color buffer to show the ClearColor we called above...

gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

}

}

好,大家做了如何?
率先大家得以完成了GLSurfaceView.Renderer那几个接口,首若是兑现3个章程:onSurfaceCreated(卡塔尔(قطر‎, onSurfaceChanged(卡塔尔(قطر‎ 和 onDrawFrame(卡塔尔国。那几个艺术比较轻便精通,第三个在三星平板创造未来调用,第四个是在三星平板发生变动未来调用,举个例子从竖屏切换来横屏的时候,最终一个措施是当其余时候调用三个美术方法的时候。
从11行到13行,大家用浮点数来定义翼虎GB颜色系统中的每多少个颜料。
在28行,大家通过glClearColor(卡塔尔国方法为底色定义了颜色。底色是在我们能看见的具有东西的前边,所以具备在底色后边的东西都是不可以知道的。能够诬捏这种事物为轻雾,挡住了颇负的事物。然后我们就要为之设置间距来show一下它怎么用的。那时你就自然会通晓它是怎么存在的了。
为了让颜色变化可以预知,大家必需调用glClear(卡塔尔国以至颜色缓冲的Mask来清空buffer,然后为大家的底色使用新的底色。
     为了能看出它在起效果,大家那边为Motion伊夫nt创立三个response,使用它来退换颜色。首先在VortexRenderer中来创立叁个装置颜色的函数。

public void setColor(float r, float g, float b) {

    _red = r;

    _green = g;

    _blue = b;

}

上边是VortexView类中创制的措施来管理MotionEvent。

public boolean onTouchEvent(final MotionEvent event) {

queueEvent(new Runnable() {

public void run() {

_renderer.setColor(event.getX() / getWidth(), event.getY() / getHeight(), 1.0f);

}

});

return true;

}

复制代码

我们创造了一个无名氏的Runnable对象,这里的run(卡塔尔(英语:State of Qatar)方法调用renderer中的setColor方法。那有会依照MotionEvent坐标做一些小的精兵简政。
近日我们曾经有了三个十分的小程序来利用OpenGl来退换我们的背景色了。
    在日语中大家叫这种小case为“Mit Kanonen auf Spatzen schießen”,翻译过来应该是“你在轮子上打死了二头苍蝇”。那说的适合,那只是一个最最细微的事例,要学习OpenGL,你今后要预备越多越多的事物。
那某些结尾提一下OpenGL的文书档案documentation for OpenGL 。那么些事物固然可用想不高,可是它最少是三个文书档案。

此地是多少个截图:  


那么些类别的第二部分是有关怎么着加多贰个三角形并能够旋转它。
率先件专门的学问是伊始化须求呈现的三角形。大家来在VortexRenderer类中增多四个方式initTriangle(卡塔尔。

// new object variables we need

// a raw buffer to hold indices

private ShortBuffer _indexBuffer;

 

// a raw buffer to hold the vertices

private FloatBuffer _vertexBuffer;

 

private short[] _indicesArray = {0, 1, 2};

private int _nrOfVertices = 3;

 

// code snipped

 

private void initTriangle() {

    // float has 4 bytes

    ByteBuffer vbb = ByteBuffer.allocateDirect(_nrOfVertices * 3 * 4);

    vbb.order(ByteOrder.nativeOrder());

    _vertexBuffer = vbb.asFloatBuffer();

 

    // short has 2 bytes

    ByteBuffer ibb = ByteBuffer.allocateDirect(_nrOfVertices * 2);

    ibb.order(ByteOrder.nativeOrder());

    _indexBuffer = ibb.asShortBuffer();

必发365电子游戏, 

    float[] coords = {

        -0.5f, -0.5f, 0f, // (x1, y1, z1)

        0.5f, -0.5f, 0f, // (x2, y2, z2)

        0f, 0.5f, 0f // (x3, y3, z3)

    };

 

    _vertexBuffer.put(coords);

    _indexBuffer.put(_indicesArray);

 

    _vertexBuffer.position(0);

    _indexBuffer.position(0);

}

让大家从新的靶子变量初叶. _vertexBuffer为大家的三角保存坐标._indexBuffer保存索引. _nrOfVertices变量定义必要几个极点.对于贰个三角形来讲,风流浪漫共须要多少个极点.
      这些格局首先为此地多个buffer分配必得的内存(14-22行卡塔尔国. 接下去我们定义一些坐标(24-28行卡塔尔(قطر‎ 前边的讲明对用场给与了表达.
      在30行,我们将coords数组填充给_vertexBuffer . 相像在31行将indices数组填充给_indexBuffer 。最终将多少个buffer都设置position为0.
为了防止每一遍都对三角形实行伊始化,大家只有在onDrawFrame(卡塔尔国早前的行数调用它一次。三个相比较好的拈轻怕重正是在onSurfaceCreated(卡塔尔函数中.

@Override

public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    // preparation

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    initTriangle();

}

glEnableClientState() 设置OpenGL使用vertex数组来画。那是很主要的,因为只要不这么设置OpenGL不清楚怎么样管理大家的数额。接下来大家将在起初化大家的三角。
何以我们不需利用不一样的buffer? 在新的onDrawFrame(卡塔尔(英语:State of Qatar)方法中我们不得不加多一些新的OpenGL调用。

@Override

public void onDrawFrame(GL10 gl) {

// define the color we want to be displayed as the "clipping wall"

gl.glClearColor(_red, _green, _blue, 1.0f);

 

// clear the color buffer to show the ClearColor we called above...

gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

 

// set the color of our element

gl.glColor4f(0.5f, 0f, 0f, 0.5f);

 

// define the vertices we want to draw

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);

 

// finally draw the vertices

gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);

}

好,一步一步地看。
glClearColor(卡塔尔国 和 glClear(卡塔尔(قطر‎在教程I部分已经涉嫌过。在第10行使用glColor4f(red, green, blue, 阿尔法卡塔尔国设置三角形为暗水晶色 .
在第13行,我们使用glVertexPointer(卡塔尔(قطر‎最初化Vertex Pointer. 第三个参数是高低,也是终点的维数。大家利用的是x,y,z三个维度坐标。第一个参数,GL_FLOAT定义buffer中采纳的数据类型。第四个变量是0,是因为我们的坐标是在数组中紧密的排列的,未有行使offset。最终哦胡第多个参数极点缓冲。
最后,glDrawElements(卡塔尔(英语:State of Qatar)将富有那一个因素画出来。第二个参数定义了怎么着的图元将被画出来。第贰个参数定义有微微个因素,第多个是indices使用的数据类型。最后二个是绘制极点使用的索引缓冲。
当最终测验那些应用的施用,你拜候到两个在荧屏中间静止的三角。当你点击荧屏的时候,显示器的背景颜色照旧会更改。
今后往里面增多对三角形的旋转。下边包车型大巴代码是写在VortexRenderer类中的.

private float _angle;

 

public void setAngle(float angle) {

_angle = angle;

}

glRotatef()方法在glColor4f()之前被onDrawFrame()调用.

@Override

public void onDrawFrame(GL10 gl) {

// set rotation

gl.glRotatef(_angle, 0f, 1f, 0f);

 

gl.glColor4f(0.5f, 0f, 0f, 0.5f);

// code snipped

}

 

那会儿大家得以绕y轴转动。假如供给改换只须求退换glRotate(卡塔尔方法中的0f。这么些参数中的值表示二个向量,标识三角形绕着旋转的坐标轴。
要让它可用,大家一定要在VortexView中的onTouch伊芙nt(卡塔尔(قطر‎中加多叁个调用。

public boolean onTouchEvent(final MotionEvent event) {

    queueEvent(new Runnable() {

        public void run() {

            _renderer.setColor(event.getX() / getWidth(), event.getY() / getHeight(), 1.0f);

            _renderer.setAngle(event.getX() / 10);

        }

    });

    return true;

}

地方代码中除以10是为着减少角度转换的进度。
当今编写翻译运转那些顺序。若是您在显示屏的最侧边点击,你会看出三角形微微旋转。借令你将手指移到左臂,旋转的进程就能够变得超快。  

 

在这里个类别的第三有些给您show一下哪些甘休三角形的团团转,并告诉你本来的旋转其实只是在三角上海展览中心开的转动,并不是在摄像机“camera”上拓宽的团团转。
咱俩盼望能对旋转进行更加多的支配。为此,在每一趟调用onDrawFrame(卡塔尔(قطر‎方法的时候都会重新设置这几个矩阵。那会重设三角形的角度以便其三番一次能够转动到给定的角度。

@Override

public void onDrawFrame(GL10 gl) {

    // define the color we want to be displayed as the "clipping wall"

    gl.glClearColor(_red, _green, _blue, 1.0f);

 

    // reset the matrix - good to fix the rotation to a static angle

    gl.glLoadIdentity();

 

    // clear the color buffer and the depth buffer to show the ClearColor

    // we called above...

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

 

    // code snipped

}

在VortexView类中,你应该删除“除以10”以便其得以转动范围越来越大学一年级部分。

_renderer.setAngle(event.getX());

 

假诺尝试了这几个,你将会看到旋转只会依照触摸的到的地点来旋转。若无触动荧屏,旋转不会时有产生转移。
下意气风发件事情:大家旋转的是三角形自个儿,还是旋转的view/camera?
为了阐明它,最简便易行的点子是创办第4个不旋转的三角实行自己检查自纠。
最快也是最笨的艺术是copy&paste initTriangle(卡塔尔(قطر‎方法为三个新的不二等秘书技initStaticTriangle(卡塔尔(قطر‎,copy&paste当中的七个buffer,copy&paste并改过onDrawFrame(卡塔尔(قطر‎方法中的最后四行。
不用忘记了更换第三个三角的颜色以至更动第三个三角形的坐标,那样有助于大家能来看多少个三角。小编将各个地方的0.5f都改成了0.4f.
那边是全方位的类:

package com.droidnova.android.games.vortex;

 

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;

 

import android.opengl.GLSurfaceView;

 

public class VortexRenderer implements GLSurfaceView.Renderer {

    private static final String LOG_TAG = VortexRenderer.class.getSimpleName();

 

    private float _red = 0f;

    private float _green = 0f;

    private float _blue = 0f;

 

    // a raw buffer to hold indices allowing a reuse of points.

    private ShortBuffer _indexBuffer;

    private ShortBuffer _indexBufferStatic;

 

    // a raw buffer to hold the vertices

    private FloatBuffer _vertexBuffer;

    private FloatBuffer _vertexBufferStatic;

 

    private short[] _indicesArray = {0, 1, 2};

    private int _nrOfVertices = 3;

 

    private float _angle;

 

    @Override

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

        // preparation

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        initTriangle();

        initStaticTriangle();

    }

 

    @Override

    public void onSurfaceChanged(GL10 gl, int w, int h) {

        gl.glViewport(0, 0, w, h);

    }

 

    public void setAngle(float angle) {

        _angle = angle;

    }

 

    @Override

    public void onDrawFrame(GL10 gl) {

        // define the color we want to be displayed as the "clipping wall"

        gl.glClearColor(_red, _green, _blue, 1.0f);

 

        // reset the matrix - good to fix the rotation to a static angle

        gl.glLoadIdentity();

 

        // clear the color buffer to show the ClearColor we called above...

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

 

        // draw the static triangle

        gl.glColor4f(0f, 0.5f, 0f, 0.5f);

        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBufferStatic);

        gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBufferStatic);

 

        // set rotation for the non-static triangle

        gl.glRotatef(_angle, 0f, 1f, 0f);

 

        gl.glColor4f(0.5f, 0f, 0f, 0.5f);

        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);

        gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);

 

    }

 

    private void initTriangle() {

        // float has 4 bytes

        ByteBuffer vbb = ByteBuffer.allocateDirect(_nrOfVertices * 3 * 4);

        vbb.order(ByteOrder.nativeOrder());

        _vertexBuffer = vbb.asFloatBuffer();

 

        // short has 4 bytes

        ByteBuffer ibb = ByteBuffer.allocateDirect(_nrOfVertices * 2);

        ibb.order(ByteOrder.nativeOrder());

        _indexBuffer = ibb.asShortBuffer();

 

        float[] coords = {

            -0.5f, -0.5f, 0f, // (x1, y1, z1)

            0.5f, -0.5f, 0f, // (x2, y2, z2)

            0f, 0.5f, 0f // (x3, y3, z3)

        };

 

        _vertexBuffer.put(coords);

 

        _indexBuffer.put(_indicesArray);

 

        _vertexBuffer.position(0);

        _indexBuffer.position(0);

    }

 

    private void initStaticTriangle() {

        // float has 4 bytes

        ByteBuffer vbb = ByteBuffer.allocateDirect(_nrOfVertices * 3 * 4);

        vbb.order(ByteOrder.nativeOrder());

        _vertexBufferStatic = vbb.asFloatBuffer();

 

        // short has 4 bytes

        ByteBuffer ibb = ByteBuffer.allocateDirect(_nrOfVertices * 2);

        ibb.order(ByteOrder.nativeOrder());

        _indexBufferStatic = ibb.asShortBuffer();

 

        float[] coords = {

            -0.4f, -0.4f, 0f, // (x1, y1, z1)

            0.4f, -0.4f, 0f, // (x2, y2, z2)

            0f, 0.4f, 0f // (x3, y3, z3)

        };

 

        _vertexBufferStatic.put(coords);

 

        _indexBufferStatic.put(_indicesArray);

 

        _vertexBufferStatic.position(0);

        _indexBufferStatic.position(0);

    }

 

    public void setColor(float r, float g, float b) {

        _red = r;

        _green = g;

        _blue = b;

    }

}

尽管作了上述这一个,你拜见到只有一个三角形能够旋转。假使您想多少个都得以转动,只须求在“draw the static triangle”那个注释的豆蔻梢头旁也给它助长意气风发行代码就足以了。
编译并运维这么些程序,你能够看看灰湖绿的三角形在转悠,同时浅紫的三角依然呆在本来之处。
那也丰硕表达了咱们的答案,大家旋转的只是三角形并不是整个场景。

 

本条体系的第四片段讲怎么给三角形增添颜色。
在上部分大家创制了第3个静态的三角来证实大家旋转的是三角形并不是全体地方。这里大家将以此静态的三角形删除掉。删除掉initStaticTriangle(卡塔尔函数,删除五个buffer,_indexBufferStatic和_vertexBufferStatic。同有时候也要去除原本初阶静止三角形时用到的onDrawFrame(卡塔尔中的最终四行。
新的onDrawFrame(卡塔尔(英语:State of Qatar)方法如下:

@Override

public void onDrawFrame(GL10 gl) {

    // define the color we want to be displayed as the "clipping wall"

    gl.glClearColor(_red, _green, _blue, 1.0f);

 

    // reset the matrix - good to fix the rotation to a static angle

    gl.glLoadIdentity();

 

    // clear the color buffer to show the ClearColor we called above...

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

 

    // set rotation for the non-static triangle

    gl.glRotatef(_angle, 0f, 1f, 0f);

 

    gl.glColor4f(0.5f, 0f, 0f, 0.5f);

    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);

    gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);

}

到现在大家为保留颜色音信创造三个新的buffer。那一个_colorBuffer是一个目的变量,不过大家需要在initTriangle(卡塔尔(英语:State of Qatar)方法中定义颜色并填写这一个buffer.

// code snipped

 

// a raw buffer to hold the colors

private FloatBuffer _colorBuffer;

 

// code snipped

private void initTriangle() {

    // float has 4 bytes

    ByteBuffer vbb = ByteBuffer.allocateDirect(_nrOfVertices * 3 * 4);

    vbb.order(ByteOrder.nativeOrder());

    _vertexBuffer = vbb.asFloatBuffer();

 

    // short has 4 bytes

    ByteBuffer ibb = ByteBuffer.allocateDirect(_nrOfVertices * 2);

    ibb.order(ByteOrder.nativeOrder());

    _indexBuffer = ibb.asShortBuffer();

 

    // float has 4 bytes, 4 colors (RGBA) * number of vertices * 4 bytes

    ByteBuffer cbb = ByteBuffer.allocateDirect(4 * _nrOfVertices * 4);

    cbb.order(ByteOrder.nativeOrder());

    _colorBuffer = cbb.asFloatBuffer();

 

    float[] coords = {

        -0.5f, -0.5f, 0f, // (x1, y1, z1)

        0.5f, -0.5f, 0f, // (x2, y2, z2)

        0.5f, 0.5f, 0f // (x3, y3, z3)

    };

 

    float[] colors = {

        1f, 0f, 0f, 1f, // point 1

        0f, 1f, 0f, 1f, // point 2

        0f, 0f, 1f, 1f, // point 3

    };

 

    _vertexBuffer.put(coords);

    _indexBuffer.put(_indicesArray);

    _colorBuffer.put(colors);

 

    _vertexBuffer.position(0);

    _indexBuffer.position(0);

    _colorBuffer.position(0);

}

咱俩创造了一个FloatBuffer类型的对象变量_colorBuffer(第四行)。在initTriangle(卡塔尔(英语:State of Qatar)方法中大家为新的颜色buffer分配了十足多的内部存储器(19-21行卡塔尔国。接下来我们创制了叁个float数组(23-27行),每一个终端有4个值。 那个协会是讴歌ZDXGBA(Red,Green,Blue,阿尔法)的,所以首先个极端是红颜色,第2个颜色是青绿,第三个颜色是群青。最终两部和_vertexBuffer相通。大家将颜色数组放到buffer里面,将buffer的position设置为0.
当那几个准备职业都做完了之后,大家初阶告诉OpenGL ES使用我们的水彩数组。那通过glEnableClientState(卡塔尔,乃至glColorPointer(卡塔尔(英语:State of Qatar)来达成,和vertexBuffer相符。

@Override

public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    // preparation

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

    initTriangle();

}

 

// code snipped

 

@Override

public void onDrawFrame(GL10 gl) {

    // code snipped

 

    // gl.glColor4f(0.5f, 0f, 0f, 0.5f);

    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);

    gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);

    gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);

}

第五行大家enable了color mode。在17行大家设置了颜色 pointer。参数4表示PAJEROGBA(EnclaveGBA恰巧是多个值),其余的几个参数大家都比较熟稔了。
兴许你也看出了,大家讲授掉了15行,因为大家运用的是color mode,所以不再需求glColor4f。它会覆盖,所以大家得以注注释掉大概去除掉她。

 

游刃有余的第五片段讲如若制造你的率先个蓬蓬勃勃体化的3D对象。那几个case中是八个4面包车型客车金字塔。
为了让大家接下去的开采更便于,这里必要做一些预备。
咱俩亟须将计算buffer以至开创数组时的大变得特别动态。

private int _nrOfVertices = 0;

 

private void initTriangle() {

    float[] coords = {

            // coodinates

    };

    _nrOfVertices = coords.length;

 

    float[] colors = {

            // colors

    };

 

    short[] indices = new short[] {

            // indices

    };

 

    // float has 4 bytes, coordinate * 4 bytes

    ByteBuffer vbb = ByteBuffer.allocateDirect(coords.length * 4);

    vbb.order(ByteOrder.nativeOrder());

    _vertexBuffer = vbb.asFloatBuffer();

 

    // short has 2 bytes, indices * 2 bytes

    ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);

    ibb.order(ByteOrder.nativeOrder());

    _indexBuffer = ibb.asShortBuffer();

 

    // float has 4 bytes, colors (RGBA) * 4 bytes

    ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);

    cbb.order(ByteOrder.nativeOrder());

    _colorBuffer = cbb.asFloatBuffer();

 

    _vertexBuffer.put(coords);

    _indexBuffer.put(indices);

    _colorBuffer.put(colors);

 

    _vertexBuffer.position(0);

    _indexBuffer.position(0);

    _colorBuffer.position(0);

}

为了进一层的动态,大家必需改动部分变量以便我们接下去的做事。让我们来审视一下:
在第一行你能够见见,大家最早化_nrOfVertices为0,因为大家得以在第七行这里经过坐标的轻重缓急来规定它。
大家同期也将_indecesArray改为部分变量indices,并在13行开展了初阶化。
本条buffer创制进度被放在了坐标、颜色以致极点数组的底下,因为buffer大小决定于数组。所以请看17-18行,22-23行,27-28行。在疏解里面作者说明了计算方式。
根本的益处是,我们得以创立越来越多的vertices,而不用手动重新总括有微微个vertices,以至数组和buffer的尺寸。

下一步:你要求明白OpenGL怎样绘制并决定大家看来的事物。
相持于OpenGL来讲OpenGL ES叁个超级大的弱项正是除了三角形以外没有其余图元类型。大家未有任何多边形,所以大家想要创立的具有的对象都必得由三角形构成。笔者援用贰个blog的帖子来表明那几个难题: 苹果手提式有线电话机 developer ,同不常间也引进她的那么些作品 OpenGL ES series.
此地有越来越多的关于三角形的东西你供给精通。在OpenGL中,有三个定义叫做卷曲(winding),意思是vertices绘制时的朝气蓬勃风华正茂。与现实世界中的对象差别,OpenGL中的多边形平常从不几个面。他们唯有一个面,平日是正经,二个三角形只有当其正当面临观望者的时候才得以被看见。可以布署OpenGL将多个多边形作为两面包车型大巴,不过暗许情状下三角形唯有三个凸现的面。知道了这里是多方面形的纯正未来,OpenGL就足以少做二分之一的总计量。倘使设置两面都可视,则供给多的乘除。
纵然如此有的时候候多个多方形会独立地出示,可是你恐怕不是可怜必要它的北侧突显,常常三个三角形是八个更加大的指标的大器晚成有个别,多边形的单向就要这里个物体的在那之中,所以永久也不会被见到。这些从未被出示的黄金时代边被称作背面,OpenGl通过绘制的顺序来规定非常面是纠正哪个是背面。极点遵照逆时针绘制的是纯正(私下认可是那样,不过足以被转移)。因为OpenGL能超轻便地规定什么三角形对顾客是可视的,它就足以由此采纳Backface Culling来防止为那多少个不出示在前头的多方形做无用功。我们将要下生龙活虎篇文章里研讨意见的主题材料,然而你以后能够虚构它为二个设想录制机,或然经过一个虚构的窗口来观看OpenGL的世界。

在上头的暗中表示图中,左侧血牙玉米黄的的三角形是背面,将不会被绘制,因为它相对于观看者来讲是顺时针的。而在左边的那几个三角是正当,将会被绘制,因为绘制极点的顺序相对于观望者来讲是逆时针的。
因为我们想做的是创造三个绝妙的金字塔,大家首先disable那些glClearColor(卡塔尔国。大家得以去除掉变量_red, _green, _blue,还会有方法setColor(卡塔尔. 咱们也想退换视角,所以大家将旋转分的x和y轴上。

public class VortexRenderer implements GLSurfaceView.Renderer {

private static final String LOG_TAG = VortexRenderer.class.getSimpleName();

 

// a raw buffer to hold indices allowing a reuse of points.

private ShortBuffer _indexBuffer;

 

// a raw buffer to hold the vertices

private FloatBuffer _vertexBuffer;

 

// a raw buffer to hold the colors

private FloatBuffer _colorBuffer;

 

private int _nrOfVertices = 0;

 

private float _xAngle;

private float _yAngle;

 

@Override

public void onSurfaceCreated(GL10 gl, EGLConfig config) {

// code snipped

}

 

@Override

public void onSurfaceChanged(GL10 gl, int w, int h) {

gl.glViewport(0, 0, w, h);

}

 

public void setXAngle(float angle) {

_xAngle = angle;

}

 

public float getXAngle() {

return _xAngle;

}

 

public void setYAngle(float angle) {

_yAngle = angle;

}

 

public float getYAngle() {

return _yAngle;

}

// code snipped

 

为了保障您那边有了和那边一样的靶子变量,笔者也将那么些都贴到那个类的上面了。你能够看来大家现在有五个float变量,_xAngle和_yAngle(15-16行卡塔尔(قطر‎还会有他们的setter和getter方法(28-42行卡塔尔
今昔让大家落实基于触摸屏来总结角度的逻辑,为了做那个,需求先微微改换一下VortexView类。

// code snipped

 

private float _x = 0;

private float _y = 0;

 

// code snipped

 

public boolean onTouchEvent(final MotionEvent event) {

    if (event.getAction() == MotionEvent.ACTION_DOWN) {

        _x = event.getX();

        _y = event.getY();

    }

    if (event.getAction() == MotionEvent.ACTION_MOVE) {

        final float xdiff = (_x - event.getX());

        final float ydiff = (_y - event.getY());

        queueEvent(new Runnable() {

            public void run() {

                _renderer.setXAngle(_renderer.getXAngle() + ydiff);

                _renderer.setYAngle(_renderer.getYAngle() + xdiff);

            }

        });

        _x = event.getX();

        _y = event.getY();

    }

    return true;

}

在第3和4行大家有七个变量给大家的x和y值使用。当移动时,我们在ACTION_DOWN事件中安装他们的值,我们依据MotionEvent来计量当前值和旧的值的差。计算他们的差并加到已经使用的角度上。不要被ydiff 加多到x-angle上照旧xdiff增加到y-angle上而吸引。你可以伪造,借使你想x轴的值不变,而张开旋转,独有在y轴上旋转。对于y轴也一致。
若是我们向左也许升高移入手指,xdiff/ydiff的值就能够形成负的,旋转就能向后旋转。所以在此多少个轴上旋转都比较便于。
当今到了丰裕有意思的片段:金字塔。
像下边我们所引用的大器晚成律,winding需求某个设置。有的或然是暗许的设置,但是大家依旧定义一下,为了安全起见。

@Override

public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    // preparation

    // enable the differentiation of which side may be visible

    gl.glEnable(GL10.GL_CULL_FACE);

    // which is the front? the one which is drawn counter clockwise

    gl.glFrontFace(GL10.GL_CCW);

    // which one should NOT be drawn

    gl.glCullFace(GL10.GL_BACK);

 

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

 

    initTriangle();

}

在第5行,大家enable了culling面,以保障独有一面。在第7行大家定义了那种顺序是前方。GL_CCW表示逆时针。在第9行,大家最后定义了老大面作为culling 面。 沃恩设置其为GL_BACK以保证只显示正面。那只怕有些迷糊偶,你能够看看假使用GL_FRONT_AND_BACK会产生什么……你将什么也看不到。

@Override

public void onDrawFrame(GL10 gl) {

// define the color we want to be displayed as the "clipping wall"

gl.glClearColor(0f, 0f, 0f, 1.0f);

 

// reset the matrix - good to fix the rotation to a static angle

gl.glLoadIdentity();

 

// clear the color buffer to show the ClearColor we called above...

gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

 

// set rotation

gl.glRotatef(_xAngle, 1f, 0f, 0f);

gl.glRotatef(_yAngle, 0f, 1f, 0f);

 

//gl.glColor4f(0.5f, 0f, 0f, 0.5f);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);

gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);

gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);

}

在第四行你能够见到背景观是杏红,因为我们早已去除了原先设置的动态颜色。在13和14行你能够看看在每一种轴的旋转角度。此外的都和原先讲过的如出风流洒脱辙。
终极意气风发件事情你须求做的是校订initTriangle(卡塔尔(英语:State of Qatar)函数中的颜色数组,坐标和目录。我们的金子谈应该出示成这标准的。

private void initTriangle() {

    float[] coords = {

            -0.5f, -0.5f, 0.5f, // 0

            0.5f, -0.5f, 0.5f, // 1

            0f, -0.5f, -0.5f, // 2

            0f, 0.5f, 0f, // 3

    };

    _nrOfVertices = coords.length;

 

    float[] colors = {

            1f, 0f, 0f, 1f, // point 0 red

            0f, 1f, 0f, 1f, // point 1 green

            0f, 0f, 1f, 1f, // point 2 blue

            1f, 1f, 1f, 1f, // point 3 white

    };

 

    short[] indices = new short[] {

            0, 1, 3, // rwg

            0, 2, 1, // rbg

            0, 3, 2, // rbw

            1, 2, 3, // bwg

    };

 

    //code snipped

}

正如你在图上看到的均等,大家的金字塔有4个角。种种角都有协和的坐标,所以大家有4个极点须要定义。如2-7行。
每二个顶峰有温馨的水彩,在10-15行定义。
在上游有个别交给了定义三角形所须要的目录。时刻记着winding,三角形0,1,3和0,3,1是不雷同的。
每贰个索引点指向coords数组中定义的极端。
编写翻译运路程序,看一下只要您转移了indices的逐一会时有发生怎么着,只怕看一下借使您将GL_CCW改成GL_CW以往将会见到咋样。

 

 

本条种类的第六有些至关心保养即便有关什么成立正确的思想,因为如果没有科学的视角,3D就向来不任何意义。
在开端早前大家必要先斟酌一下OpenGL提供的那三种view:正交和投影。
正交Orthographic (无消失点投影卡塔尔国
正交视图无法看出一个实体是隔断本身可能正在大家前边。为何?因为它不会依据间隔减少。所以若是你大器晚成旦你画三个定位大小的实体在视点后面,相同的时候画二个均等大小的物体在首先个物体的远后方,你不能说那二个物体是率先个。因为三个都是同意气风发的朗朗上口,根间距非亲非故。他们不会趁机间隔而裁减。
透视Perspective (有消失点投影卡塔尔(英语:State of Qatar)
透视视图和大家从眼睛看来的视图是风流洒脱律的。比如,三个壮汉的人站在您前边,你看起来是相当高的。假使此人站在100米以外,他居然还一向不你的大拇指大。他看起来会趁机间距而压缩,不过大家实在都晓得,它照旧是个高个子。这种效用叫做透视。上面例子中提到的八个物体,第二个物体将会展现地更加小,所以大家得以分别哪些是离我们近的物体,那二个是离大家远的实体。
因为本身的例证恐怕让您会吸引。作者再也推荐那个blog帖子:HUAWEI development: OpenGL ES From the Ground Up, Part 3: Viewports in Perspective,那一个中使用依旧轨道作为例子。
咱俩想成立的第贰个view是哟娜orthographic。这些创造进度只需求贰次,正是在历次苹果平板被created的时候。所以大家需求改一下代码。一些在onDrawFrame(卡塔尔(قطر‎中的方法将在被改形成onSurfaceCreated(卡塔尔方法中。那样他们只会当程序运维恐怕旋转的时候被实践。

@Override

public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    // preparation

必发365电子游戏眼下最全的Android OpenGL文书档案。    // define the color we want to be displayed as the "clipping wall"

    gl.glClearColor(0f, 0f, 0f, 1.0f);

 

    // enable the differentiation of which side may be visible

    gl.glEnable(GL10.GL_CULL_FACE);

    // which is the front? the one which is drawn counter clockwise

    gl.glFrontFace(GL10.GL_CCW);

    // which one should NOT be drawn

    gl.glCullFace(GL10.GL_BACK);

 

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

 

    initTriangle();

}

 

// code snipped

 

@Override

public void onDrawFrame(GL10 gl) {

    gl.glLoadIdentity();

 

    // clear the color buffer and the depth buffer to show the ClearColor

    // we called above...

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

 

    // set rotation

    gl.glRotatef(_xAngle, 1f, 0f, 0f);

    gl.glRotatef(_yAngle, 0f, 1f, 0f);

 

    //gl.glColor4f(0.5f, 0f, 0f, 0.5f);

    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);

    gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);

    gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);

}

复制代码

您能够阅览大家未有将glClear(卡塔尔和glLoadIdentity(卡塔尔方法从onDrawFrame(卡塔尔国移动到onSurfaceCreate中。原因超粗略:他们会在每豆蔻梢头帧都被绘制。
因为我们要求动用显示器尺寸来计量显示屏的百分比,所以大家引进了多少个指标变量:_width和_height。大家须要在onSurfaceChanged(卡塔尔(英语:State of Qatar)方法中安装,在每趟旋转改造的时候调用。

private float _width = 320f;

private float _height = 480f;

 

@Override

public void onSurfaceChanged(GL10 gl, int w, int h) {

_width = w;

_height = h;

gl.glViewport(0, 0, w, h);

}

前段时间大家早就有了开发银行四个视点所须要的具备东西。大家供给订正一下onSurfaceChanged(卡塔尔(英语:State of Qatar)方法。

@Override

public void onSurfaceCreated(GL10 gl, EGLConfig config) {

gl.glMatrixMode(GL10.GL_PROJECTION);

float ratio = _width / _height;

// orthographic:

gl.glOrthof(-1, 1, -1 / ratio, 1 / ratio, 0.01f, 100.0f);

gl.glViewport(0, 0, (int) _width, (int) _height);

gl.glMatrixMode(GL10.GL_MODELVIEW);

gl.glEnable(GL10.GL_DEPTH_TEST);

 

// define the color we want to be displayed as the "clipping wall"

gl.glClearColor(0f, 0f, 0f, 1.0f);

 

// enable the differentiation of which side may be visible

gl.glEnable(GL10.GL_CULL_FACE);

// which is the front? the one which is drawn counter clockwise

gl.glFrontFace(GL10.GL_CCW);

// which one should NOT be drawn

gl.glCullFace(GL10.GL_BACK);

 

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

 

initTriangle();

}

Wow,今后有了广大的新代码,别怕,大家一步一步来。
在第三行,大家能够见见glMatrixMode(卡塔尔,使用GL10.GL_RPOJECTION作为参数,在第8行大家能够再次观望这几个主意,可是是运用GL10.GL_MODELVIEW作为变量。那样使用的原由是3-8行中间的代码。在此几行中,4-7行设置了我们的视点,所以我们设置了小编们的黑影。在9-17行,大家设置了大家的模子情形。在个中左右文中,两种调用使用不一样的参数应该是可以预知道的。Tips:常常能够试着去删除掉生机勃勃部分代码行来看一下结实。那样比较简单明白怎么代码行是起什么固守的。
第四行总括下同样要求的显示屏比率。在这里行中(6行)大家设置大家的视点来做orthographic view。这么些参数是为界线设定,顺序是这么的:left, right, bottom, top, zNear, zFar。
在第7行大家设置了视点。大家了解那个点子的用法因为大家已经在onSurfaceChanged(卡塔尔中央银行使过了。
在第8行大家切换了MatrixMode到GL10.GL_MODELVIEW,设置OpenGL选拔有关退换model绘制格局的调用。
第9行大家调用了glEnable(卡塔尔国并选取参数GL10.GL_DEPTH_TEST.那使OpenGL ES检核查象的z-order。假如我们并未有enable它,大家将见到最终被绘制的对象平素显示在最前头。这表示,及时固然这么些物体本来应该被更近越来越大的物体隐蔽,我们依然得以观望它。
    其余代码行我们曾在日前的几篇中早就介绍过了。
透视视图与之相像,只是不一致之处是或不是行使glOrthof(卡塔尔(قطر‎而是利用glFrustumf(卡塔尔(英语:State of Qatar). glFrustumf(卡塔尔(قطر‎函数的参数和glOrthof(卡塔尔(英语:State of Qatar)的参数略有不一样。因为我们未有收缩物体,可是大家定义的锥体将被漏不以为意状切开。看一下以此图片来打探一下glOrthof(卡塔尔国和glFrustumf(卡塔尔(قطر‎的分别。

正交Orthographic:

透视Perspective:

回去我们的代码:

@Override

public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    Log.i(LOG_TAG, "onSurfaceCreated()");

    gl.glMatrixMode(GL10.GL_PROJECTION);

    float size = .01f * (float) Math.tan(Math.toRadians(45.0) / 2);

    float ratio = _width / _height;

    // perspective:

    gl.glFrustumf(-size, size, -size / ratio, size / ratio, 0.01f, 100.0f);

    // orthographic:

    //gl.glOrthof(-1, 1, -1 / ratio, 1 / ratio, 0.01f, 100.0f);

    gl.glViewport(0, 0, (int) _width, (int) _height);

    gl.glMatrixMode(GL10.GL_MODELVIEW);

    gl.glEnable(GL10.GL_DEPTH_TEST);

 

    // define the color we want to be displayed as the "clipping wall"

    gl.glClearColor(0f, 0f, 0f, 1.0f);

 

    // enable the differentiation of which side may be visible

    gl.glEnable(GL10.GL_CULL_FACE);

    // which is the front? the one which is drawn counter clockwise

    gl.glFrontFace(GL10.GL_CCW);

    // which one should NOT be drawn

    gl.glCullFace(GL10.GL_BACK);

 

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

 

    initTriangle();

}

Information: 大家要深深记住计算变量大小(5行),大家将会看出当大家议论矩阵的时候它怎么能用。
在第8行大家选拔glFrustumf(卡塔尔(قطر‎替代glOrthof(卡塔尔(英语:State of Qatar).那是我们在orthographic view 和perspective view此前切换时索要做的富有的浮动。
可是,hey,还应该有最生平机勃勃项大家就能够看出结果了。OK,让我们改一下onDrawFrame(卡塔尔国方法吧。

@Override

public void onDrawFrame(GL10 gl) {

// clear the color buffer and the depth buffer

gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

 

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);

gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);

 

for (int i = 1; i <= 10; i++) {

gl.glLoadIdentity();

gl.glTranslatef(0.0f, -1f, -1.0f + -1.5f * i);

// set rotation

gl.glRotatef(_xAngle, 1f, 0f, 0f);

gl.glRotatef(_yAngle, 0f, 1f, 0f);

gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);

}

}

OK,大家改造了什么样?
其三行,大家改革了参数确定保证depth buffer也会被拔除。
在第9行,大家起头二个巡回来创立12个物体。
在第10行,大家看出glLoadIdentity(卡塔尔(قطر‎. 现在它在当时重设矩阵。 那是必得做的因为我们要动用glRotatef(卡塔尔和glTranslatef(卡塔尔国来改革我们的实体。但是为了保险大家只校订了这几天轮回到的实体,大家调用glLoadIndentify(卡塔尔(英语:State of Qatar)。所以大家重设每三个对早先物提的glTranslatef(卡塔尔(英语:State of Qatar)和glRotatef(卡塔尔国调用。
在11行我们看看新的glTranslatef(卡塔尔(قطر‎方法,将大家的物体移动到别的七个岗位。在此个例子中,我们不更改x轴上的职分。但是大家修正y轴上的-1.0f,那意味它仿佛大家的荧屏低等。最终的推测你能够见到,只是改良z轴的任务,表示物体的神对。第二个物体在-2.5f,第一个在-4.0f等等。所以我们将13个物体摆放在了显示器的中心。
如果你利用glFrustumf(卡塔尔调用,你看看的是这种结果:

假定您切换glFrustumf(卡塔尔(قطر‎和glOrthof(卡塔尔(英语:State of Qatar) ,你将拜访到这种结果:

Hey等一下,为啥只见二个实体?因为在正交情状下我们从未此外的阴影。所以每二个独体的实体都有相符的大小所以未有缩放,所以未有其它没有的点,所以其实全数的实体都在率先个物体的前面。

 

OK~

Over~

上一篇:没有了
下一篇:没有了