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

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

先看效果图



圆面的绘制:

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

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

圆面和圆柱侧面公式推导过程

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值