[Java] [OpenGL ES 3.2] 光照

着色器

v.vert

#version 320 es
layout(location=0)in vec3 a_position;
layout(location=1)in vec4 a_color;
out vec4 v_color;
uniform mat4 u_projection;
uniform mat4 u_view;
uniform mat4 u_model;
void main()
{
gl_Position = u_projection * u_view * u_model * vec4(a_position,1.0f);
v_color = a_color;
gl_PointSize = 100.0f;
}

f.frag

#version 320 es
precision mediump float;
in vec4 v_color;
out vec4 o_color;
void main()
{
o_color = v_color;
}

illumination.vert

#version 320 es
layout(location=0)in vec3 a_position;
layout(location=1)in vec4 a_color;
layout(location=2)in vec3 a_normal;
out vec4 v_color;
out vec3 v_normal;
out vec3 v_position;
uniform mat4 u_projection;
uniform mat4 u_view;
uniform mat4 u_model;
void main()
{
gl_Position = u_projection * u_view * u_model * vec4(a_position,1.0f);
v_color = vec4(0.0f,0.0f,1.0f,1.0f);
v_normal = normalize((u_model * vec4(a_normal,1.0f)).xyz);
v_position = (u_model * vec4(a_position,1.0f)).xyz;
}

illumination.frag

#version 320 es
precision mediump float;
in vec4 v_color;
in vec3 v_normal;
in vec3 v_position;
out vec4 o_color;
uniform vec4 u_lightcolor;
uniform vec3 u_lightposition;
void main()
{
vec3 lightdir = normalize(u_lightposition - v_position);
float diff = max(dot(v_normal,lightdir),0.0f);
o_color = (0.1f + diff) * u_lightcolor * v_color;
}

程序

Axis.java

package com.Diamond.gl03;

import android.opengl.GLES32;
import java.nio.FloatBuffer;
import com.Diamond.gl03.Program;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import android.renderscript.Float4;
import android.opengl.Matrix;
import android.renderscript.Matrix4f;

public class Axis extends MyObject {
    public float[] vertices,colors;
	public GLES32 gl;
	
	public Axis() {
		vertices = new float[]{
			-100,0,0,
			100,0,0,
			0,-100,0,
			0,100,0,
			0,0,-100,
			0,0,100
		};
		
		colors = new float[]{
			1,0,0,
			1,0,0,
			0,1,0,
			0,1,0,
			0,0,1,
			0,0,1
		};
	}
	
	public void draw(Program program) {
		program.setUniform("u_model",getModelMatrixArray());
		program.enableVertexAttrib(0,vertices);
		program.enableVertexAttrib(1,colors);
		gl.glDrawArrays(gl.GL_LINES,0,6);
	}
}

Camera.java

package com.Diamond.gl03;

import android.opengl.Matrix;
import android.renderscript.Matrix4f;
import android.renderscript.Float3;

public class Camera {
	private Float3 mPosition;
	private Float3 mCenter;
	private Float3 mUp;
	private Matrix4f mProjection;
    
	public Camera(Float3 position,Float3 center,Float3 up) {
		mPosition = position;
		mCenter = center;
		mUp = up;
		mProjection = new Matrix4f();
	}
	
	public Camera setPosition(Float3 position) {
		mPosition = position;
		return this;
	}
	
	public Camera move(Float3 distance) {
		mPosition.x += distance.x;
		mPosition.y += distance.y;
		mPosition.z += distance.z;
		return this;
	}
	
	public Camera moveX(float distance) {
		mPosition.x += distance;
		return this;
	}
	
	public Camera moveY(float distance) {
		mPosition.y += distance;
		return this;
	}
	
	public Camera moveZ(float distance) {
		mPosition.z += distance;
		return this;
	}
	
	public Camera setCenter(Float3 center) {
		mCenter = center;
		return this;
	}
	
	public Camera setUp(Float3 up) {
		mUp = up;
		return this;
	}
	
	public Camera setPerspective(float fovy,float aspect,float near,float far) {
		mProjection.loadPerspective(fovy,aspect,near,far);
		return this;
	}
	
	public Camera setOrtho(float l,float r,float b,float t,float n,float f) {
		mProjection.loadOrtho(l,r,b,t,n,f);
		return this;
	}
	
	public float[] getProjectionMatrix() {
		return mProjection.getArray();
	}
	
	public float[] getViewMatrix() {
		float[] view = new float[16];
		Matrix.setLookAtM(
						view,0,
						mPosition.x,mPosition.y,mPosition.z,
						mCenter.x,mCenter.y,mCenter.z,
						mUp.x,mUp.y,mUp.z
						);
		return view;
	}
}

Cube.java
p.s.这个类有点问题

package com.Diamond.gl03;

public class Cube extends MyObject {
    public Plane[] planes;
	
	public Cube() {
		planes = new Plane[6];
		for(int i = 0;i < planes.length;i++) {
			planes[i] = new Plane();
		}
		
		setScale(1);
	}
	
	@Override
	public Cube setScale(float s) {
		for(Plane i : planes) {
			i.reset();
			i.setScale(s);
		}
	    planes[0].moveZ(s);
		planes[1].rotateX(180).moveZ(-s);
		planes[2].rotateX(90).moveY(s);
		planes[3].rotateX(-90).moveY(-s);
		planes[4].rotateY(90).moveX(s);
		planes[5].rotateY(-90).moveX(-s);
	    return this;
	}
	
	public Cube draw(Program program,boolean illumination) {
		for(Plane i : planes) {
			i.draw(program,illumination);
		}
		return this;
	}
}

Light.java

package com.Diamond.gl03;

import android.renderscript.Float4;
import android.opengl.GLES32;

public class Light extends MyObject {
	public float lightIntensity;
	public Float4 lightColor;
	public GLES32 gl;
	
    public Light() {
		lightIntensity = 1;
		lightColor = new Float4(1,1,1,1);
	}
	
	public Light draw(Program program) {
		program.setUniform("u_model",getModelMatrixArray());
		program.enableVertexAttrib(0,new float[]{0,0,0});
		program.enableVertexAttrib(1,new float[]{lightColor.x,lightColor.y,lightColor.z,lightColor.w});
		gl.glDrawArrays(gl.GL_POINTS,0,1);
		return this;
	}
}

MainActivity.java

package com.Diamond.gl03;
 
import android.app.Activity;
import android.os.Bundle;
import android.widget.RelativeLayout;

public class MainActivity extends Activity { 
	MySurfaceView surfaceView;
	RelativeLayout relativeLayout1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
		surfaceView = new MySurfaceView(this);
		surfaceView.requestFocus();
		surfaceView.setFocusableInTouchMode(true);
		setContentView(surfaceView);
    }
	
} 

MyObject.java

package com.Diamond.gl03;

import android.opengl.GLES32;
import android.renderscript.Matrix4f;
import android.renderscript.Float3;

public class MyObject {
    private Matrix4f mModel;
	private Float3 mPosition;
	private Float3 mRotate;
	private Float3 mScale;
	
	public MyObject() {
		mModel = new Matrix4f();
		mModel.loadIdentity();
		
		mPosition = new Float3(0,0,0);
		mRotate = new Float3(0,0,0);
		mScale = new Float3(1,1,1);
	}
	
	public MyObject reset() {
		mModel.loadIdentity();
		return this;
	}
	
	public MyObject setPosition(Float3 position) {
		mPosition = position;
		updateModelMatrix();
		return this;
	}
	public MyObject move(Float3 d) {
		mPosition.x += d.x;
		mPosition.y += d.y;
		mPosition.z += d.z;
		updateModelMatrix();
		return this;
	}
	public MyObject moveX(float d) {
		mPosition.x += d;
		updateModelMatrix();
		return this;
	}
	public MyObject moveY(float d) {
		mPosition.y += d;
		updateModelMatrix();
		return this;
	}
	public MyObject moveZ(float d) {
		mPosition.z += d;
		updateModelMatrix();
		return this;
	}
	public Float3 getPosition() {
		return mPosition;
	}
	
	public MyObject setRotate(Float3 rotate) {
		mRotate = rotate;
		updateModelMatrix();
		return this;
	}
	public MyObject rotate(Float3 d) {
		mRotate.x += d.x;
		mRotate.y += d.y;
		mRotate.z += d.z;
		updateModelMatrix();
		return this;
	}
	public MyObject rotateX(float d) {
		mRotate.x += d;
		updateModelMatrix();
		return this;
	}
	public MyObject rotateY(float d) {
		mRotate.y += d;
		updateModelMatrix();
		return this;
	}
	public MyObject rotateZ(float d) {
		mRotate.z += d;
		updateModelMatrix();
		return this;
	}
	public Float3 getRotate() {
		return mRotate;
	}
	
	public MyObject setScale(Float3 scale) {
		mScale = scale;
		updateModelMatrix();
		return this;
	}
	public MyObject setScale(float s) {
		return setScale(new Float3(s,s,s));
	}
	public Float3 getScale() {
		return mScale;
	}
	
	public MyObject setModelMatrix(Matrix4f matrix) {
		mModel.load(matrix);
		return this;
	}
	
	public float[] getModelMatrixArray() {
		return getModelMatrix().getArray();
	}
	public Matrix4f getModelMatrix() {
		return mModel;
	}
	
	public MyObject updateModelMatrix() {
		mModel.loadIdentity();
		mModel.translate(mPosition.x,mPosition.y,mPosition.z);
		mModel.rotate(mRotate.x,1,0,0);
		mModel.rotate(mRotate.y,0,1,0);
		mModel.rotate(mRotate.z,0,0,1);
		mModel.scale(mScale.x,mScale.y,mScale.z);
		return this;
	}
}

MySurfaceView.java

package com.Diamond.gl03;

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.renderscript.Float3;
import com.Diamond.gl03.Plane;
import com.Diamond.gl03.Program;
import com.Diamond.gl03.Camera;

public class MySurfaceView extends GLSurfaceView {
    public class MyRenderer implements GLSurfaceView.Renderer {
		public Plane plane;
		public Camera camera;
		public Program program,illumination;
		public GLES32 gl;
		public Axis axis;
		public Cube cube;
		public Light light;

        @Override
        public void onSurfaceCreated(GL10 p1, EGLConfig p2) {
            plane = new Plane();
			plane.setScale(0.5f);
			
			cube = new Cube();
			//cube.setScale(0.5f); 这个函数有问题
			
			camera = new Camera(new Float3(3, 3, 3), new Float3(0, 0, 0), new Float3(0, 1, 0));
			camera.setPerspective(120.0f, 0.5f, 0.1f, 100.0f);

			String vStr = Program.loadFromAssetsFile("v.vert", getResources());
			String fStr = Program.loadFromAssetsFile("f.frag", getResources());
			program = new Program(vStr, fStr);
			
			String vIllStr = Program.loadFromAssetsFile("illumination.vert",getResources());
			String fIllStr = Program.loadFromAssetsFile("illumination.frag",getResources());
			illumination = new Program(vIllStr,fIllStr);
			
			axis = new Axis();
			
			light = new Light();
			light.setPosition(new Float3(-2,-2,2));

			gl.glEnable(gl.GL_DEPTH_TEST);
			//面剔除 Cube类有问题,如果你发现有几个面缺了,那很正常
			/*gl.glEnable(gl.GL_CULL_FACE);
			gl.glFrontFace(gl.GL_CW);
			gl.glCullFace(gl.GL_CCW);*/
        }

        @Override
        public void onSurfaceChanged(GL10 p1, int p2, int p3) {

        }

        @Override
        public void onDrawFrame(GL10 p1) {
			gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);
			gl.glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
			
            program.useProgram();
			program.setUniform("u_projection", camera.getProjectionMatrix());
			program.setUniform("u_view", camera.getViewMatrix());
			axis.draw(program);
			light.draw(program);
			//plane.draw(program);
			
			illumination.useProgram();
			illumination.setUniform("u_projection",camera.getProjectionMatrix());
			illumination.setUniform("u_view",camera.getViewMatrix());
			illumination.setUniform("u_lightcolor",light.lightColor);
			illumination.setUniform("u_lightposition",light.getPosition());
			plane.draw(illumination,true);
			cube.draw(illumination,true);
			
			light.move(new Float3(0.01f,0.01f,0.0f));
        }
    }

    private MyRenderer renderer;
    public MySurfaceView(Context context) {
        super(context);
        this.setEGLContextClientVersion(3);
        renderer = new MyRenderer();
        this.setRenderer(renderer);
        this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }
}

Plane.java

package com.Diamond.gl03;

import android.opengl.GLES32;
import com.Diamond.gl03.Plane;
import com.Diamond.gl03.MyObject;
import java.nio.FloatBuffer;
import java.util.Random;
import java.nio.IntBuffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public class Plane extends MyObject {
    public IntBuffer indices;
	public float[] vertices,colors,normals;
	public GLES32 gl;
	public Random random;
	
	public Plane() {
		random = new Random();
		random.setSeed(System.currentTimeMillis());
		
		vertices = new float[]{
			-1.0f,1.0f,0.0f,
			-1.0f,-1.0f,0.0f,
			1.0f,1.0f,0.0f,
			1.0f,-1.0f,0.0f
		};
		
		normals = new float[]{
			0,0,1,
			0,0,1,
			0,0,1,
			0,0,1
		};
		
		colors = new float[4 * 4];
		for(int i = 0;i < colors.length;i += 4) {
			colors[i] = random();
			colors[i + 1] = random();
			colors[i + 2] = random();
			colors[i + 3] = 1;
		}
		
		int[] ind = new int[]{
			1,0,2,
			1,2,3
		};
		ByteBuffer bb = ByteBuffer.allocateDirect(ind.length * 4);
		bb.order(ByteOrder.nativeOrder());
		indices = bb.asIntBuffer();
		indices.put(ind);
		indices.position(0);
	}
	
	public Plane draw(Program program,boolean enableIllumination) {
		program.setUniform("u_model",getModelMatrixArray());
		program.enableVertexAttrib(0,vertices);
		program.enableVertexAttrib(1,colors);
		if(enableIllumination) {
			program.enableVertexAttrib(2,normals);
		}
		gl.glDrawElements(gl.GL_TRIANGLES,6,gl.GL_UNSIGNED_INT,indices);
		return this;
	}
	
	public float random() {
		return random.nextFloat();
	}
}

Program.java


package com.Diamond.gl03;

import android.opengl.GLES32;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import android.renderscript.Float2;
import android.renderscript.Float3;
import android.renderscript.Float4;
import java.io.InputStream;
import android.content.res.Resources;
import java.io.ByteArrayOutputStream;
import java.nio.FloatBuffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import android.text.style.LocaleSpan;

public class Program {
    public class Shader {
        private int program;
        private int type;
        public final String tag = "failed to load shader";

        private void loadShader(String resource) {
            program = GLES32.glCreateShader(type);
            if (program == 0) {
                Log.e(tag, "shader program type:" + type);
                Log.e(tag, "error:" + GLES32.glGetError());
                return;
            }
            GLES32.glShaderSource(program, resource);
            GLES32.glCompileShader(program);
            int[] compiled = new int[1];
            GLES32.glGetShaderiv(program, GLES32.GL_COMPILE_STATUS, compiled, 0);
            if (compiled[0] == 0) {
                Log.e(tag, GLES32.glGetShaderInfoLog(program));
                GLES32.glDeleteShader(program);
                program = 0;
            }
        }

        public Shader(int programType) {
            program = 0;
            type = programType;
        }
        public Shader(int programType, String resource) {
            type = programType;
            loadShader(resource);
        }

        public int getProgram() {
            return program;
        }
    }

    private Shader vShader;
    private Shader fShader;
    private Shader gShader;
    private int program;
    private final String tag = "failed to create program";

    private void linkProgram() {
        int vp = vShader.getProgram();
        int fp = fShader.getProgram();
        int gp = gShader.getProgram();
        program = GLES32.glCreateProgram();
        if (program == 0) {
            Log.e(tag, "" + GLES32.glGetError());
            return;
        }
        GLES32.glAttachShader(program, vp);
        GLES32.glAttachShader(program, fp);
        if (gp != 0) {
            GLES32.glAttachShader(program, gp);
        }
        GLES32.glLinkProgram(program);
        int[] linkStatus = new int[1];
        GLES32.glGetProgramiv(program, GLES32.GL_LINK_STATUS, linkStatus, 0);
        if (linkStatus[0] == GLES32.GL_FALSE) {
            Log.e(tag, GLES32.glGetProgramInfoLog(program));
            GLES32.glDeleteProgram(program);
            program = 0;
        }
    }

    public Program() {
        vShader = new Shader(GLES32.GL_VERTEX_SHADER);
        fShader = new Shader(GLES32.GL_FRAGMENT_SHADER);
        gShader = new Shader(GLES32.GL_GEOMETRY_SHADER);
        linkProgram();
    }
    public Program(String vResource, String fResource) {
        vShader = new Shader(GLES32.GL_VERTEX_SHADER, vResource);
        fShader = new Shader(GLES32.GL_FRAGMENT_SHADER, fResource);
        gShader = new Shader(GLES32.GL_GEOMETRY_SHADER);
        linkProgram();
    }
    public Program(String vResource, String fResource, String gResource) {
        vShader = new Shader(GLES32.GL_VERTEX_SHADER, vResource);
        fShader = new Shader(GLES32.GL_FRAGMENT_SHADER, fResource);
        gShader = new Shader(GLES32.GL_GEOMETRY_SHADER, gResource);
        linkProgram();
    }

    public int getProgram() {
        return program;
    }
    public Program useProgram() {
        GLES32.glUseProgram(program);
		return this;
    }

	public static String loadFromAssetsFile(String fname, Resources resources) {
		String result=null;    	
		try {
			InputStream in=resources.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;
	}
	
	public static FloatBuffer toFloatBuffer(float[] array) {
		ByteBuffer bb = ByteBuffer.allocateDirect(array.length * 4);
		bb.order(ByteOrder.nativeOrder());
		FloatBuffer fb = bb.asFloatBuffer();
		fb.put(array);
		fb.position(0);
		return fb;
	}
	
	public static void enableVertexAttrib(int loc) {
		GLES32.glEnableVertexAttribArray(loc);
	}
	public static void postVertex(int loc,float[] vertices) {
		GLES32.glVertexAttribPointer(loc,3,GLES32.GL_FLOAT,false,0,toFloatBuffer(vertices));
	}
	public static void enableVertexAttrib(int loc,float[] vertices) {
		enableVertexAttrib(loc);
		postVertex(loc,vertices);
	}
	public static void disableVertexAttrib(int loc) {
		GLES32.glDisableVertexAttribArray(loc);
	}
	
    public int getUniformLocation(String name) {
        return GLES32.glGetUniformLocation(program, name);
    }
    public Program setUniform(String name, float value) {
        int location = getUniformLocation(name);
        GLES32.glUniform1f(location, value);
		return this;
    }
    public Program setUniform(String name, int value) {
        int location = getUniformLocation(name);
        GLES32.glUniform1i(location, value);
		return this;
    }
    public Program setUniform(String name, float value1, float value2) {
        int location = getUniformLocation(name);
        GLES32.glUniform2f(location, value1, value2);
		return this;
    }
    public Program setUniform(String name, Float2 value) {
        setUniform(name, value.x, value.y);
		return this;
    }
    public Program setUniform(String name, float value1, float value2, float value3) {
        int location = getUniformLocation(name);
        GLES32.glUniform3f(location, value1, value2, value3);
		return this;
    }
    public Program setUniform(String name, Float3 value) {
        setUniform(name, value.x, value.y, value.z);
		return this;
    }
    public Program setUniform(String name, float value1, float value2, float value3, float value4) {
        int location = getUniformLocation(name);
        GLES32.glUniform4f(location, value1, value2, value3, value4);
		return this;
    }
    public Program setUniform(String name, Float4 value) {
        setUniform(name, value.x, value.y, value.z, value.w);
		return this;
    }
    public Program setUniform(String name, float[] matrix) {
        int location = getUniformLocation(name);
        GLES32.glUniformMatrix4fv(location, 1, false, matrix, 0);
		return this;
    }
}

效果图

如果没问题,最后结果应该如图所示
[Java] [OpenGL ES 3.2] 光照_第1张图片
[Java] [OpenGL ES 3.2] 光照_第2张图片

你可能感兴趣的:(OpenGL/OpenGL,ES/EGL,java,opengles,android)