opengles绘制圆锥体(光照+纹理)

来源:互联网 发布:威海淘宝代运营 编辑:程序博客网 时间:2024/04/29 02:44

转自:http://blog.csdn.net/hb707934728/article/details/52470649

效果图


圆面的绘制

[java] view plain copy
  1. package test.com.opengles8_2;  
  2.   
  3. /** 
  4.  * Created by hbin on 2016/9/7. 
  5.  */  
  6.   
  7. import java.nio.ByteBuffer;  
  8. import java.nio.ByteOrder;  
  9. import java.nio.FloatBuffer;  
  10. import android.opengl.GLES20;  
  11.   
  12.   
  13. public class Circle {  
  14.     int mProgram;//自定义渲染管线着色器程序id  
  15.     int muMVPMatrixHandle;//总变换矩阵引用  
  16.     int maPositionHandle; //顶点位置属性引用  
  17.     int maTexCoorHandle; //顶点纹理坐标属性引用  
  18.     int muMMatrixHandle;  
  19.   
  20.     int maCameraHandle; //摄像机位置属性引用  
  21.     int maNormalHandle; //顶点法向量属性引用  
  22.     int maLightLocationHandle;//光源位置属性引用  
  23.   
  24.   
  25.     String mVertexShader;//顶点着色器代码脚本  
  26.     String mFragmentShader;//片元着色器代码脚本  
  27.   
  28.     FloatBuffer   mVertexBuffer;//顶点坐标数据缓冲  
  29.     FloatBuffer   mTexCoorBuffer;//顶点纹理坐标数据缓冲  
  30.     FloatBuffer   mNormalBuffer;//顶点法向量数据缓冲  
  31.     int vCount=0;  
  32.     float xAngle=0;//绕x轴旋转的角度  
  33.     float yAngle=0;//绕y轴旋转的角度  
  34.     float zAngle=0;//绕z轴旋转的角度  
  35.   
  36.     public Circle(MySurfaceView mv,float scale,float r,int n)  
  37.     {  
  38.         //调用初始化顶点数据的initVertexData方法  
  39.         initVertexData(scale,r,n);  
  40.         //调用初始化着色器的intShader方法  
  41.         initShader(mv);  
  42.     }  
  43.   
  44.     //自定义的初始化顶点数据的方法  
  45.     public void initVertexData(  
  46.             float scale,    //大小  
  47.             float r,        //半径  
  48.             int n)      //切分的份数  
  49.     {  
  50.         r=r*scale;  
  51.         float angdegSpan=360.0f/n;  //顶角的度数  
  52.         vCount=3*n;//顶点个数,共有n个三角形,每个三角形都有三个顶点  
  53.   
  54.         float[] vertices=new float[vCount*3];//坐标数据  
  55.         float[] textures=new float[vCount*2];//顶点纹理S、T坐标值数组  
  56.         //坐标数据初始化  
  57.         int count=0;  
  58.         int stCount=0;  
  59.         for(float angdeg=0;Math.ceil(angdeg)<360;angdeg+=angdegSpan)  
  60.         {  
  61.             double angrad=Math.toRadians(angdeg);//当前弧度  
  62.             double angradNext=Math.toRadians(angdeg+angdegSpan);//下一弧度  
  63.             //中心点  
  64.             vertices[count++]=0;//顶点坐标  
  65.             vertices[count++]=0;  
  66.             vertices[count++]=0;  
  67.   
  68.             textures[stCount++]=0.5f;//st坐标  
  69.             textures[stCount++]=0.5f;  
  70.             //当前点  
  71.             vertices[count++]=(float) (-r*Math.sin(angrad));//顶点坐标  
  72.             vertices[count++]=(float) (r*Math.cos(angrad));  
  73.             vertices[count++]=0;  
  74.   
  75.             textures[stCount++]=(float) (0.5f-0.5f*Math.sin(angrad));//st坐标  
  76.             textures[stCount++]=(float) (0.5f-0.5f*Math.cos(angrad));  
  77.             //下一点  
  78.             vertices[count++]=(float) (-r*Math.sin(angradNext));//顶点坐标  
  79.             vertices[count++]=(float) (r*Math.cos(angradNext));  
  80.             vertices[count++]=0;  
  81.   
  82.             textures[stCount++]=(float) (0.5f-0.5f*Math.sin(angradNext));//st坐标  
  83.             textures[stCount++]=(float) (0.5f-0.5f*Math.cos(angradNext));  
  84.         }  
  85.         ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点坐标数据缓冲  
  86.         vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序  
  87.         mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲  
  88.         mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据  
  89.         mVertexBuffer.position(0);//设置缓冲区起始位置  
  90.         //法向量数据初始化  
  91.         float[] normals=new float[vertices.length];  
  92.         for(int i=0;i<normals.length;i+=3){  
  93.             normals[i]=0;  
  94.             normals[i+1]=0;  
  95.             normals[i+2]=1;  
  96.         }  
  97.         ByteBuffer nbb = ByteBuffer.allocateDirect(normals.length*4);//创建顶点法向量数据缓冲  
  98.         nbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序  
  99.         mNormalBuffer = nbb.asFloatBuffer();//转换为float型缓冲  
  100.         mNormalBuffer.put(normals);//向缓冲区中放入顶点法向量数据  
  101.         mNormalBuffer.position(0);//设置缓冲区起始位置  
  102.   
  103.         //纹理坐标数据初始化  
  104.         ByteBuffer cbb = ByteBuffer.allocateDirect(textures.length*4);//创建顶点纹理数据缓冲  
  105.         cbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序  
  106.         mTexCoorBuffer = cbb.asFloatBuffer();//转换为float型缓冲  
  107.         mTexCoorBuffer.put(textures);//向缓冲区中放入顶点纹理数据  
  108.         mTexCoorBuffer.position(0);//设置缓冲区起始位置  
  109.     }  
  110.   
  111.     //自定义初始化着色器initShader方法  
  112.     public void initShader(MySurfaceView mv){  
  113.         //加载顶点着色器的脚本内容  
  114.         mVertexShader=ShaderUtil.loadFromAssetsFile("vertex_tex_light.sh", mv.getResources());  
  115.         //加载片元着色器的脚本内容  
  116.         mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_tex_light.sh", mv.getResources());  
  117.         //基于顶点着色器与片元着色器创建程序  
  118.         mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader);  
  119.         //获取程序中顶点位置属性引用id  
  120.         maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");  
  121.         //获取程序中顶点纹理坐标属性引用id  
  122.         maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");  
  123.         //获取程序中总变换矩阵引用id  
  124.         muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");  
  125.         //获取程序中顶点法向量属性引用id  
  126.         maNormalHandle= GLES20.glGetAttribLocation(mProgram, "aNormal");  
  127.         //获取程序中摄像机位置引用id  
  128.         maCameraHandle=GLES20.glGetUniformLocation(mProgram, "uCamera");  
  129.         //获取程序中光源位置引用id  
  130.         maLightLocationHandle=GLES20.glGetUniformLocation(mProgram, "uLightLocation");  
  131.         //获取位置、旋转变换矩阵引用id  
  132.         muMMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMMatrix");  
  133.     }  
  134.   
  135.     public void drawSelf(int texId)  
  136.     {  
  137.         //制定使用某套shader程序  
  138.         GLES20.glUseProgram(mProgram);  
  139.   
  140.         //将最终变换矩阵传入shader程序  
  141.         GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1false, MatrixState.getFinalMatrix(), 0);  
  142.   
  143.         //将位置、旋转变换矩阵传入shader程序  
  144.         GLES20.glUniformMatrix4fv(muMMatrixHandle, 1false, MatrixState.getMMatrix(), 0);  
  145.         //将摄像机位置传入shader程序  
  146.         GLES20.glUniform3fv(maCameraHandle, 1, MatrixState.cameraFB);  
  147.         //将光源位置传入shader程序  
  148.         GLES20.glUniform3fv(maLightLocationHandle, 1, MatrixState.lightPositionFB);  
  149.   
  150.   
  151.         //传送顶点位置数据  
  152.         GLES20.glVertexAttribPointer  
  153.                 (  
  154.                         maPositionHandle,  
  155.                         3,  
  156.                         GLES20.GL_FLOAT,  
  157.                         false,  
  158.                         3*4,  
  159.                         mVertexBuffer  
  160.                 );  
  161.         //传送顶点纹理坐标数据  
  162.         GLES20.glVertexAttribPointer  
  163.                 (  
  164.                         maTexCoorHandle,  
  165.                         2,  
  166.                         GLES20.GL_FLOAT,  
  167.                         false,  
  168.                         2*4,  
  169.                         mTexCoorBuffer  
  170.                 );  
  171.         //传送顶点法向量数据  
  172.         GLES20.glVertexAttribPointer  
  173.                 (  
  174.                         maNormalHandle,  
  175.                         4,  
  176.                         GLES20.GL_FLOAT,  
  177.                         false,  
  178.                         3*4,  
  179.                         mNormalBuffer  
  180.                 );  
  181.   
  182.         //启用顶点位置数据  
  183.         GLES20.glEnableVertexAttribArray(maPositionHandle);  
  184.         //启用顶点纹理数据  
  185.         GLES20.glEnableVertexAttribArray(maTexCoorHandle);  
  186.         //启用顶点法向量数据  
  187.         GLES20.glEnableVertexAttribArray(maNormalHandle);  
  188.   
  189.   
  190.         //绑定纹理  
  191.         GLES20.glActiveTexture(GLES20.GL_TEXTURE0);  
  192.         GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);  
  193.   
  194.         //绘制纹理矩形  
  195.         GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vCount);  
  196.     }  
  197. }  

圆锥侧面的绘制

[java] view plain copy
  1. package test.com.opengles8_2;  
  2.   
  3. import java.nio.ByteBuffer;  
  4. import java.nio.ByteOrder;  
  5. import java.nio.FloatBuffer;  
  6. import android.opengl.GLES20;  
  7.   
  8.   
  9. /** 
  10.  * Created by hbin on 2016/9/7. 
  11.  * 圆锥侧面 
  12.  */  
  13. public class ConeSide {  
  14.     int mProgram;//自定义渲染管线着色器程序id  
  15.     int muMVPMatrixHandle;//总变换矩阵引用  
  16.     int maPositionHandle; //顶点位置属性引用  
  17.     int maTexCoorHandle; //顶点纹理坐标属性引用  
  18.   
  19.     int muMMatrixHandle;//位置、旋转、缩放变换矩阵  
  20.     int maCameraHandle; //摄像机位置属性引用  
  21.     int maNormalHandle; //顶点法向量属性引用  
  22.     int maLightLocationHandle;//光源位置属性引用  
  23.   
  24.     String mVertexShader;//顶点着色器代码脚本  
  25.     String mFragmentShader;//片元着色器代码脚本  
  26.   
  27.     FloatBuffer   mVertexBuffer;//顶点坐标数据缓冲  
  28.     FloatBuffer   mTexCoorBuffer;//顶点纹理坐标数据缓冲  
  29.     FloatBuffer   mNormalBuffer;//顶点法向量数据缓冲  
  30.     int vCount=0;  
  31.     float xAngle=0;//绕x轴旋转的角度  
  32.     float yAngle=0;//绕y轴旋转的角度  
  33.     float zAngle=0;//绕z轴旋转的角度  
  34.   
  35.     public ConeSide(MySurfaceView mv,float scale,float r,float h,int n)  
  36.     {  
  37.         //调用初始化顶点数据的initVertexData方法  
  38.         initVertexData(scale,r,h,n);  
  39.         //调用初始化着色器的intShader方法  
  40.         initShader(mv);  
  41.     }  
  42.   
  43.     //自定义初始化顶点坐标数据的方法  
  44.     public void initVertexData(  
  45.             float scale,    //尺寸大小  
  46.             float r,    //半径  
  47.             float h,    //高度  
  48.             int n       //切分的份数  
  49.     )  
  50.     {  
  51.         r=scale*r;  
  52.         h=scale*h;  
  53.         float angdegSpan=360.0f/n;  
  54.         vCount=3*n*4;//顶点个数,共有3*n*4个三角形,每个三角形都有三个顶点  
  55.         //坐标数据初始化  
  56.         float[] vertices=new float[vCount*3];  
  57.         float[] textures=new float[vCount*2];//顶点纹理S、T坐标值数组  
  58.         float[] normals=new float[vertices.length];//法向量数组  
  59.         //坐标数据初始化  
  60.         int count=0;  
  61.         int stCount=0;  
  62.         int norCount=0;  
  63.         for(float angdeg=0;Math.ceil(angdeg)<360;angdeg+=angdegSpan)//侧面  
  64.         {  
  65.             double angrad=Math.toRadians(angdeg);//当前弧度  
  66.             double angradNext=Math.toRadians(angdeg+angdegSpan);//下一弧度  
  67.             //顶点(圆锥最高的点)  
  68.             vertices[count++]=0;  
  69.             vertices[count++]=h;  
  70.             vertices[count++]=0;  
  71.             //纹理坐标  
  72.             textures[stCount++]=0.5f;//st坐标  
  73.             textures[stCount++]=0;  
  74.   
  75.             //当前点  
  76.             vertices[count++]=(float) (-r*Math.sin(angrad));  
  77.             vertices[count++]=0;  
  78.             vertices[count++]=(float) (-r*Math.cos(angrad));  
  79.             //纹理坐标  
  80.             textures[stCount++]=(float) (angrad/(2*Math.PI));  
  81.             textures[stCount++]=1;  
  82.   
  83.             //下一点  
  84.             vertices[count++]=(float) (-r*Math.sin(angradNext));  
  85.             vertices[count++]=0;  
  86.             vertices[count++]=(float) (-r*Math.cos(angradNext));  
  87.             //纹理坐标  
  88.             textures[stCount++]=(float) (angradNext/(2*Math.PI));  
  89.             textures[stCount++]=1;  
  90.         }  
  91.   
  92.         //法向量数据的初始化  
  93.         for(int i=0;i<vertices.length;i=i+3)  
  94.         {  
  95.             //如果当前的顶点为圆锥的最高点  
  96.             if(vertices[i]==0&&vertices[i+1]==h&&vertices[i+2]==0){  
  97.                 normals[norCount++]=0;  
  98.                 normals[norCount++]=1;  
  99.                 normals[norCount++]=0;  
  100.             }else{//当前的顶点为底面圆上的顶点  
  101.                 float [] norXYZ=VectorUtil.calConeNormal(//通过三个顶点求出法向量  
  102.                         000,                        //底面圆的中心点  
  103.                         vertices[i], vertices[i+1], vertices[i+2], //当前的顶点坐标  
  104.                         0, h, 0);                       //顶点坐标(圆锥最高点)  
  105.                 normals[norCount++]=norXYZ[0];  
  106.                 normals[norCount++]=norXYZ[1];  
  107.                 normals[norCount++]=norXYZ[2];  
  108.             }  
  109.         }  
  110.   
  111.         ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点坐标数据缓冲  
  112.         vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序  
  113.         mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲  
  114.         mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据  
  115.         mVertexBuffer.position(0);//设置缓冲区起始位置  
  116.         //法向量数据初始化  
  117.         ByteBuffer nbb = ByteBuffer.allocateDirect(normals.length*4);//创建顶点法向量数据缓冲  
  118.         nbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序  
  119.         mNormalBuffer = nbb.asFloatBuffer();//转换为float型缓冲  
  120.         mNormalBuffer.put(normals);//向缓冲区中放入顶点法向量数据  
  121.         mNormalBuffer.position(0);//设置缓冲区起始位置  
  122.         //st坐标数据初始化  
  123.         ByteBuffer cbb = ByteBuffer.allocateDirect(textures.length*4);//创建顶点纹理数据缓冲  
  124.         cbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序  
  125.         mTexCoorBuffer = cbb.asFloatBuffer();//转换为float型缓冲  
  126.         mTexCoorBuffer.put(textures);//向缓冲区中放入顶点纹理数据  
  127.         mTexCoorBuffer.position(0);//设置缓冲区起始位置  
  128.     }  
  129.   
  130.     //自定义初始化着色器的initShader方法  
  131.     public void initShader(MySurfaceView mv)  
  132.     {  
  133.         //加载顶点着色器的脚本内容  
  134.         mVertexShader=ShaderUtil.loadFromAssetsFile("vertex_tex_light.sh", mv.getResources());  
  135.         //加载片元着色器的脚本内容  
  136.         mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_tex_light.sh", mv.getResources());  
  137.         //基于顶点着色器与片元着色器创建程序  
  138.         mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader);  
  139.         //获取程序中顶点位置属性引用id  
  140.         maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");  
  141.         //获取程序中顶点纹理坐标属性引用id  
  142.         maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");  
  143.         //获取程序中总变换矩阵引用id  
  144.         muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");  
  145.   
  146.         //获取程序中顶点法向量属性引用id  
  147.         maNormalHandle= GLES20.glGetAttribLocation(mProgram, "aNormal");  
  148.         //获取程序中摄像机位置引用id  
  149.         maCameraHandle=GLES20.glGetUniformLocation(mProgram, "uCamera");  
  150.         //获取程序中光源位置引用id  
  151.         maLightLocationHandle=GLES20.glGetUniformLocation(mProgram, "uLightLocation");  
  152.         //获取位置、旋转变换矩阵引用id  
  153.         muMMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMMatrix");  
  154.   
  155.   
  156.     }  
  157.   
  158.     public void drawSelf(int texId)  
  159.     {  
  160.         //制定使用某套shader程序  
  161.         GLES20.glUseProgram(mProgram);  
  162.         //将最终变换矩阵传入shader程序  
  163.         GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1false, MatrixState.getFinalMatrix(), 0);  
  164.         //将位置、旋转变换矩阵传入shader程序  
  165.         GLES20.glUniformMatrix4fv(muMMatrixHandle, 1false, MatrixState.getMMatrix(), 0);  
  166.         //将摄像机位置传入shader程序  
  167.         GLES20.glUniform3fv(maCameraHandle, 1, MatrixState.cameraFB);  
  168.         //将光源位置传入shader程序  
  169.         GLES20.glUniform3fv(maLightLocationHandle, 1, MatrixState.lightPositionFB);  
  170.   
  171.         //传送顶点位置数据  
  172.         GLES20.glVertexAttribPointer  
  173.                 (  
  174.                         maPositionHandle,  
  175.                         3,  
  176.                         GLES20.GL_FLOAT,  
  177.                         false,  
  178.                         3*4,  
  179.                         mVertexBuffer  
  180.                 );  
  181.         //传送顶点纹理坐标数据  
  182.         GLES20.glVertexAttribPointer  
  183.                 (  
  184.                         maTexCoorHandle,  
  185.                         2,  
  186.                         GLES20.GL_FLOAT,  
  187.                         false,  
  188.                         2*4,  
  189.                         mTexCoorBuffer  
  190.                 );  
  191.         //传送顶点法向量数据  
  192.         GLES20.glVertexAttribPointer  
  193.                 (  
  194.                         maNormalHandle,  
  195.                         4,  
  196.                         GLES20.GL_FLOAT,  
  197.                         false,  
  198.                         3*4,  
  199.                         mNormalBuffer  
  200.                 );  
  201.   
  202.         //启用顶点位置数据  
  203.         GLES20.glEnableVertexAttribArray(maPositionHandle);  
  204.         //启用顶点纹理数据  
  205.         GLES20.glEnableVertexAttribArray(maTexCoorHandle);  
  206.         //启用顶点法向量数据  
  207.         GLES20.glEnableVertexAttribArray(maNormalHandle);  
  208.         //绑定纹理  
  209.         GLES20.glActiveTexture(GLES20.GL_TEXTURE0);  
  210.         GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);  
  211.   
  212.         //绘制纹理矩形  
  213.         GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);  
  214.     }  
  215. }  
圆锥体顶点计算公式

0 0