android opengles光照效果-散射光
来源:互联网 发布:京东域名买谁的 编辑:程序博客网 时间:2024/05/02 01:15
向量的模:http://www.baike.com/wiki/%E5%90%91%E9%87%8F%E7%9A%84%E6%A8%A1
三维向量的模为 根号x^2 + y^2 + z^2
球面任意一点 到球心的距离都是半径R 所以x^2 + y^2 + z^2 = R^2
向量的运算:http://blog.csdn.net/he_wen_jian/article/details/25533829
求法向量:http://blog.csdn.net/lidec/article/details/51873647
opengles光照总结:http://blog.csdn.net/kesalin/article/details/8451595
散射光比环境光稍复杂,需要用到以上的一些向量知识
散射光的计算公式: 散射光照结果=材质的反射系数 x 环境光强度 x max(0, dot(N, L))
N为顶点法向量 L为光源向量
demo:
import java.io.ByteArrayOutputStream;import java.io.InputStream;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;import android.app.Activity;import android.content.Context;import android.opengl.GLES20;import android.opengl.GLSurfaceView;import android.opengl.Matrix;import android.os.Bundle;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MSur(this)); }}class MSur extends GLSurfaceView { Render render; public MSur(Context context) { super(context); this.setEGLContextClientVersion(2); render = new Render(context); setRenderer(render); this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); }}class Render implements GLSurfaceView.Renderer { private static final float r=0.8f; //TODO 1 设置光源位置 private static final float LIGHT[]={1.0f, 0.5f, 1.5f}; private int vCount; private Context ctx; private FloatBuffer fbVertex; private FloatBuffer fbNormal; private FloatBuffer fbLight; static float[] mMMatrix = new float[16]; int mProgram;// 自定义渲染管线程序id int muMVPMatrixHandle;// 总变换矩阵引用id int maPositionHandle; // 顶点位置属性引用id int maNormalHandle; //顶点法向量属性引用 int maLightLocationHandle;//光源位置属性引用 public static float[] mProjMatrix = new float[16];// 4x4矩阵 投影用 public static float[] mVMatrix = new float[16];// 摄像机位置朝向9参数矩阵 public static float[] mMVPMatrix;// 最后起作用的总变换矩阵 public Render(Context ctx) { super(); this.ctx = ctx; } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { GLES20.glClearColor(0f, 0f, 0f, 1.0f); initVertex(); initShader(); GLES20.glEnable(GLES20.GL_DEPTH_TEST); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { GLES20.glViewport(0, 0, width, height); float ratio = (float) width / height; Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 1, 10); Matrix.setLookAtM(mVMatrix, 0, 0, 0, 3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); } @Override public void onDrawFrame(GL10 gl) { GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); draw(); } public void draw() { GLES20.glUseProgram(mProgram); Matrix.setRotateM(mMMatrix, 0, 0, 0, 1, 0); mMVPMatrix = new float[16]; Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0); Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0); GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); //TODO 6 将光源位置传入着色器程序 GLES20.glUniform3fv(maLightLocationHandle, 1, fbLight); GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 3 * 4, fbVertex); //TODO 7 将顶点法向量数据传入渲染管线 GLES20.glVertexAttribPointer(maNormalHandle, 3, GLES20.GL_FLOAT, false, 3 * 4, fbNormal); GLES20.glEnableVertexAttribArray(maPositionHandle); //TODO 8 启用顶点法向量数据 GLES20.glEnableVertexAttribArray(maNormalHandle); GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount); } //初始化数据 private void initVertex() { ArrayList<Float> alVertix = new ArrayList<Float>(); final int angleSpan = 10;// 将球进行单位切分的角度 for (int vAngle = -90; vAngle < 90; vAngle = vAngle + angleSpan)// 垂直方向angleSpan度一份 { for (int hAngle = 0; hAngle <= 360; hAngle = hAngle + angleSpan)// 水平方向angleSpan度一份 { float x0 = (float) (r * Math.cos(Math.toRadians(vAngle)) * Math.cos(Math.toRadians(hAngle))); float y0 = (float) (r * Math.cos(Math.toRadians(vAngle)) * Math.sin(Math.toRadians(hAngle))); float z0 = (float) (r * Math.sin(Math .toRadians(vAngle))); float x1 = (float) (r * Math.cos(Math.toRadians(vAngle)) * Math.cos(Math.toRadians(hAngle + angleSpan))); float y1 = (float) (r * Math.cos(Math.toRadians(vAngle)) * Math.sin(Math.toRadians(hAngle + angleSpan))); float z1 = (float) (r * Math.sin(Math.toRadians(vAngle))); float x2 = (float) (r * Math.cos(Math.toRadians(vAngle + angleSpan)) * Math.cos(Math.toRadians(hAngle + angleSpan))); float y2 = (float) (r * Math.cos(Math.toRadians(vAngle + angleSpan)) * Math.sin(Math.toRadians(hAngle + angleSpan))); float z2 = (float) (r * Math.sin(Math.toRadians(vAngle + angleSpan))); float x3 = (float) (r * Math.cos(Math.toRadians(vAngle + angleSpan)) * Math.cos(Math.toRadians(hAngle))); float y3 = (float) (r * Math.cos(Math.toRadians(vAngle + angleSpan)) * Math.sin(Math.toRadians(hAngle))); float z3 = (float) (r * Math.sin(Math.toRadians(vAngle + angleSpan))); alVertix.add(x1); alVertix.add(y1); alVertix.add(z1); alVertix.add(x3); alVertix.add(y3); alVertix.add(z3); alVertix.add(x0); alVertix.add(y0); alVertix.add(z0); alVertix.add(x1); alVertix.add(y1); alVertix.add(z1); alVertix.add(x2); alVertix.add(y2); alVertix.add(z2); alVertix.add(x3); alVertix.add(y3); alVertix.add(z3); } } vCount = alVertix.size() / 3; float vertices[]=new float[alVertix.size()]; for (int i=0;i<vertices.length;i++) { vertices[i]=alVertix.get(i); } ByteBuffer bbv = ByteBuffer.allocateDirect(vertices.length * 4); bbv.order(ByteOrder.nativeOrder()); fbVertex = bbv.asFloatBuffer(); fbVertex.put(vertices); fbVertex.position(0); //TODO 4 法向量 ByteBuffer bbn = ByteBuffer.allocateDirect(vertices.length * 4); bbn.order(ByteOrder.nativeOrder()); fbNormal = bbn.asFloatBuffer(); fbNormal.put(vertices); fbNormal.position(0); //TODO 5 光源位置 ByteBuffer bbl = ByteBuffer.allocateDirect(LIGHT.length * 4); bbl.order(ByteOrder.nativeOrder()); fbLight = bbl.asFloatBuffer(); fbLight.put(LIGHT); fbLight.position(0); } //初始化shader private void initShader() { String vertex = loadSH("vertex.sh"); String shader = loadSH("frag.sh"); int verS = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); if (verS != 0) { GLES20.glShaderSource(verS, vertex); GLES20.glCompileShader(verS); } int fragS = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); if (fragS != 0) { GLES20.glShaderSource(fragS, shader); GLES20.glCompileShader(fragS); } mProgram = GLES20.glCreateProgram(); if (mProgram != 0) { GLES20.glAttachShader(mProgram, verS); GLES20.glAttachShader(mProgram, fragS); GLES20.glLinkProgram(mProgram); } maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition"); muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); //TODO 2 获取程序中顶点法向量属性引用 maNormalHandle= GLES20.glGetAttribLocation(mProgram, "aNormal"); //TODO 3 获取程序中光源位置引用 maLightLocationHandle=GLES20.glGetUniformLocation(mProgram, "uLightLocation"); } //将sh文件加载进来 private String loadSH(String fname) { String result = null; try { InputStream in = ctx.getAssets().open(fname); int ch = 0; ByteArrayOutputStream baos = new ByteArrayOutputStream(); while ((ch = in.read()) != -1) { baos.write(ch); } byte[] buff = baos.toByteArray(); baos.close(); in.close(); result = new String(buff, "UTF-8"); result = result.replaceAll("\\r\\n", "\n"); } catch (Exception e) { e.printStackTrace(); } return result; }}
vertex.sh
uniform mat4 uMVPMatrix; //总变换矩阵uniform vec3 uLightLocation; //光源位置attribute vec3 aPosition; //顶点位置attribute vec3 aNormal; //顶点法向量varying vec4 vDiffuse; //用于传递给片元着色器的散射光分量void main() { gl_Position = uMVPMatrix * vec4(aPosition,1); vec4 vAmbient = vec4(0.9, 0.9, 0.9, 1.0); //设置环境光强度 vec3 normalTarget=aPosition+aNormal; vec3 newNormal=(vec4(normalTarget,1)).xyz-(vec4(aPosition,1)).xyz; //求出法向量 newNormal=normalize(newNormal); //向量规格化 vec3 vp= normalize(uLightLocation-(vec4(aPosition,1)).xyz); //计算从表面点到光源位置的向量 vp=normalize(vp); //向量规格化 float nDotViewPosition=max(0.0, dot(newNormal,vp)); //求法向量与vp向量的点积与0的最大值 vDiffuse=vAmbient*nDotViewPosition; //计算散射光的最终强度}
frag.sh
precision mediump float;varying vec4 vDiffuse; //用于传递给片元着色器的散射光分量void main() { vec4 vFinalColor = vec4(1.0, 0.0, 1.0, 0.0); gl_FragColor = vFinalColor * vDiffuse; //通过散射光分量获得最终颜色}
效果:
0 0
- android opengles光照效果-散射光
- android opengles光照效果-环境光
- opengles绘制球体之三种光照通道的合成(环境光,散射光,镜面光)
- OpenGL ES着色语言-光照效果之散射光
- android opengles光照效果-镜面光
- openges绘制可旋转的球体-增加光照效果之散射光
- OpenGlES--光照
- 大气散射光照模型
- 大气散射光照模型
- HLSL模拟散射光
- Vertex Shader - 散射光照处理
- 着色器和效果——2.4 样例应用程序:散射光照(上)
- 着色器和效果——2.4 样例应用程序:散射光照(下)
- 大气散射效果实现
- opengles实现方向光
- android opengl es 光照效果
- Android 系列的光照效果
- android 游戏 光照效果 未完成
- 在Pyhon中通过pip方式安装numpy、matplotlib、scipy、Scikit-learn包
- SPOJ TBATTLE - Thor vs Frost Giants [数论+二分]
- AlloyTeam代码规范
- 简单IF语句的简化写法->三目运算符
- 免费馅饼
- android opengles光照效果-散射光
- http Cookie与Session的讲解
- Java_集合体系之ArrayList详解、源码及示例
- 项目中接口的作用大大滴
- team 工作问题
- MySql修改密码后PhpMyAdmin无法登陆
- Django在win10下的安装
- 指针引用的基本应用
- IOCP JSON 协议分包