MySurfaceView.java
package com.Diamond.gl09; import android.opengl.*; import android.opengl.GLES32; import android.opengl.GLSurfaceView; import android.content.Context; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.egl.EGLConfig; import android.content.res.AssetManager; import java.io.IOException; import android.renderscript.Float3; import android.renderscript.Float4; import android.view.MotionEvent; import android.util.Log; import java.util.Random; public class MySurfaceView extends GLSurfaceView { public class MyRenderer implements GLSurfaceView.Renderer { public GLES32 gl; public Program usual; public Program illumination; public MyObj[] cubes; public MyObj sphere; public Camera camera; public Axis axis; public Fog fog; public Light[] lights; public float angleX,angleY,distance; public Texture texture; public int w,h; public boolean enableFog; @Override public void onSurfaceCreated(GL10 p1, EGLConfig p2) { usual = new Program(Program.loadFromAssetsFile("usual.vert", getResources()), Program.loadFromAssetsFile("usual.frag", getResources())); illumination = new Program(Program.loadFromAssetsFile("illumination.vert", getResources()), Program.loadFromAssetsFile("illumination.frag", getResources())); texture = new Texture(getResources().openRawResource(R.raw.texture), gl.GL_TEXTURE_2D, 0); Random random = new Random(); random.setSeed(System.currentTimeMillis()); try { float scale = 0.5f; AssetManager am = getResources().getAssets(); cubes = new MyObj[1000]; MyObj cube = new MyObj(am.open("cube.obj"), new Float4()); for (int i = 0;i < cubes.length;i++) { cubes[i] = new MyObj(cube.VAO, cube.vCount); cubes[i].texture = texture; cubes[i].enableTexture = true; cubes[i].color = new Float4(random.nextFloat(), random.nextFloat(), random.nextFloat(), 1); } randomCubes(); sphere = new MyObj(am.open("sphere.obj"), new Float4(0, 0, 1, 1)); sphere.setScale(scale).moveX(0.5f); sphere.texture = texture; sphere.enableTexture = true; } catch (IOException e) { e.printStackTrace(); } angleX = 0; angleY = 0; distance = 10; camera = new Camera(new Float3(0, 0, 1), new Float3(0, 0, 0), new Float3(0, 1, 0)); updateCamera(0, 0); updateCameraP(); axis = new Axis(); fog = new Fog(1, 10, new Float4(0.1f, 0.1f, 0.1f, 1.0f)); enableFog = true; lights = new Light[4]; lights[0] = new Light(); lights[1] = new Light(); lights[1].setPosition(new Float3(0, 0, 0)); lights[2] = new Light(); lights[2].setPosition(new Float3(0, 5, 0)); lights[3] = new Light(); lights[3].setPosition(new Float3(0, -5, 0)); gl.glEnable(gl.GL_DEPTH_TEST); gl.glClearColor(0.1f, 0.1f, 0.1f, 1.0f); } @Override public void onSurfaceChanged(GL10 p1, int p2, int p3) { updateCameraP(); } @Override public void onDrawframe(GL10 p1) { gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT); usual.useProgram(); camera.draw(usual); fog.enableFog = false; fog.draw(usual); axis.draw(usual); illumination.useProgram(); illumination.setUniform("u_enableColor", true); illumination.setUniform("u_enableTexture", false); camera.draw(illumination); fog.enableFog = enableFog; fog.draw(illumination); lights[0].setPosition(camera.getPosition()); for (int i = 0;i < lights.length;i++) { lights[i].draw(illumination, i); } for (int i = 0;i < cubes.length;i++) { cubes[i].draw(illumination); } sphere.draw(illumination); } public void updateCamera(float dx, float dy) { angleX += dx; angleY += dy; camera.setOrbit(angleX, angleY, distance); } public void updateCameraP() { w = getMeasuredWidth(); h = getMeasuredHeight(); int a = Math.max(w,h); int b = Math.min(w,h); float ratio = a / b; camera.setPerspective(120.0f,0.5f,0.1f,100.0f); } public void randomCubes() { Random random = new Random(); random.setSeed(System.currentTimeMillis()); for(int i = 0;i < cubes.length;i++) { cubes[i].setPosition(new Float3(random.nextFloat() * 10 - 5, random.nextFloat() * 10 - 5, random.nextFloat() * 10 - 5)); cubes[i].setRotate(new Float3(random.nextFloat() * 360, random.nextFloat() * 360, 0)); cubes[i].setScale(random.nextFloat() * 0.5f); } } public void regularCubes() { for(int i = 0;i < cubes.length;i++) { cubes[i].setRotate(new Float3(0,0,0)); cubes[i].setScale(0.5f); int x = i / 100; int y = i / 10 % 10; int z = i % 10; cubes[i].setPosition(new Float3(x - 5,y - 5,z - 5)); //x,y,z的值怎么排都无所谓 } } } public MyRenderer renderer; public float lastX,lastY; public float speed; public MySurfaceView(Context context) { super(context); this.setEGLContextClientVersion(3); renderer = new MyRenderer(); this.setRenderer(renderer); this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); speed = 100; } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { lastX = event.getX(); lastY = event.getY(); } else if (event.getAction() == MotionEvent.ACTION_MOVE) { float nowX = event.getX(); float nowY = event.getY(); float dx = nowX - lastX; float dy = nowY - lastY; dx *= speed / 1080; dy *= speed / 2160; renderer.updateCamera(-dx, dy); lastX = nowX; lastY = nowY; } return super.onTouchEvent(event); } }
illumination.frag
#version 320 es precision highp float; in vec3 v_normal; in vec3 v_position; in vec2 v_texCoord; out vec4 o_color; uniform vec4 u_color; uniform bool u_enableColor; uniform vec3 u_cameraposition; const int lightnum = 4; struct Fog { float start; float end; vec4 color; bool enable; }; struct Light { vec3 position; vec4 color; float intensity; }; uniform Fog fog; uniform Light lights[lightnum]; uniform sampler2D texSampler; uniform bool u_enableTexture; const float constant = 1.0; const float linear = 0.045; const float quadratic = 0.0075; vec4 cal_light(Light l,vec4 color) { vec4 ambient = 0.1f * l.color; vec3 lightdir = normalize(l.position - v_position); float diff = max(dot(v_normal,lightdir),0.0f); vec4 diffuse = diff * l.color; vec3 cameradir = normalize(u_cameraposition - v_position); vec3 reflectdir = normalize(reflect(-lightdir,v_normal)); float spec = pow(max(dot(cameradir,reflectdir),0.0f),l.intensity); vec4 specular = spec * l.color; //计算衰减,这里的光源是点光源 float distance = length(l.position - v_position); float attenuation = 1.0 / (constant + linear * distance + quadratic * (distance * distance)); return (ambient + diffuse + specular) * color * attenuation; //改了,不然太亮了 } float cal_fog(Fog f) { float distance = length(u_cameraposition - v_position); float factor = (f.end - distance) / (f.end - f.start); factor = max(min(factor,1.0),0.0); return factor; } vec4 get_color() { vec4 result; if(u_enableColor) { if(u_enableTexture) { result = u_color * texture(texSampler,v_texCoord); } else { result = u_color; } } else { result = texture(texSampler,v_texCoord); } return result; } void main() { vec4 color = get_color(); vec4 lightresult = cal_light(lights[0],color); for(int i = 1;i < lightnum;i++) { lightresult += cal_light(lights[i],color); } float factor; if(fog.enable) { factor = cal_fog(fog); } else { factor = 1.0; } if(factor == 0.0) { o_color = fog.color; } else { o_color = lightresult * factor + fog.color * (1.0 - factor); } }提示
1.改了着色器,可以支持多光源了,只要
program.setUniform("lights[" + index + "].position",lights[index].getPosition()); //...
就行了
2.还把颜色分开来了,支持纹理或者纯色或者纹理*颜色作为片段照明前颜色
3.camera.draw()和light.draw()是我偷懒,把提交uniform的都并一块了
一般就这效果(1000个方块)
如果比较多(10000个方块),就会朝一个轴延伸
MainActivity的代码就不展示了,很简单的
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)