[Java] [OpenGL ES3.2] 一群方块组成的方块

[Java] [OpenGL ES3.2] 一群方块组成的方块,第1张

[Java] [OpenGL ES3.2] 一群方块组成的方块 代码

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的代码就不展示了,很简单的

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5712772.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存