[Java] [OpenGL ES 3.2] 非真实感绘制与球,圆柱体,胶囊的生成

着色器代码

v.vert

#version 320 es
precision highp float;

layout(location=0)in vec3 a_position;
layout(location=1)in vec4 a_color;
layout(location=2)in vec3 a_normal;
layout(location=3)in vec3 a_texCoord;

out vec4 v_color;
out vec3 v_normal;
out vec3 v_texCoord;
out vec3 v_position;
out vec3 v_position_no_model;

uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;

uniform bool u_isGroup;
uniform mat4 u_group_model;

void main()
{
    mat4 model = u_model;
    if(u_isGroup)
    {
        model = u_group_model * u_model;
    }
    gl_Position = u_projection * u_view * model * vec4(a_position,1.0);
    v_color = a_color;
    v_normal = normalize(vec3(u_model * vec4(a_normal,0.0)));
    v_texCoord = a_texCoord;
    v_position = vec3(u_model * vec4(a_position,1.0));
}

lighting.frag

#version 320 es
precision highp float;

in vec3 v_position_no_model;
in vec3 v_position;
in vec4 v_color;
in vec3 v_normal;
in vec3 v_texCoord;
out vec4 o_color;

uniform vec3 u_lightposition;
uniform vec3 u_cameraposition;

uniform vec4 u_color;

uniform float u_correct;

vec4 getColor()
{
	vec4 color = u_color;
    return color;
}

vec4 getLighting(vec4 color)
{
	vec3 lightdirection = normalize(v_position - u_lightposition);
    float ambient = 0.5;
    float diffuse = max(dot(v_normal,-lightdirection),0.0);
    vec3 reflectdirection = normalize(reflect(lightdirection,v_normal));
    vec3 viewdirection = normalize(u_cameraposition - v_position);
    float specular = pow(max(dot(viewdirection,reflectdirection),0.0),32.0);
    return (ambient + diffuse + specular) * color;
}

bool isInEdge()
{
    vec3 viewdirection = normalize(u_cameraposition - v_position);
    float factor = max(dot(v_normal,viewdirection),0.0);
    if(factor <= 0.1)
    {
        return true;
    }
    else
    {
        return false;
    }
}

float my_step(float value)
{
    float span = 1.0 / float(5);
    for(float i = 0.0;i <= 1.0;i += span)
    {
        if(value <= i)
        {
            return i;
        }
    }
}

vec4 my_step(vec4 color)
{
    /*color.r = my_step(color.r);
    color.g = my_step(color.g);
    color.b = my_step(color.b);*/
    return my_step(length(color) / length(vec4(1.0))) * color;
}

void main()
{
	vec4 color = getColor();
    
    if(isInEdge())
    {
        o_color = vec4(0.0);
    }
    else
    {
        color = getLighting(color);
        o_color = my_step(color);
    }
}

一个很简单的函数,用来生成球上的顶点,可以看看这篇文章了解原理

public static Float3 getVertex(float xz_angle,float y_angle) {
        float y = (float)Math.sin(Math.toRadians((float)y_angle)) * RADIUS;
        float h = (float)Math.cos(Math.toRadians((float)y_angle)) * RADIUS;
        float x = (float)Math.sin(Math.toRadians((float)xz_angle)) * h;
        float z = (float)Math.cos(Math.toRadians((float)xz_angle)) * h;
        return new Float3(x,y,z);
    }

生成球的函数

public static float[] genVertices(float xz_span,float y_span,float xz_angle_start,float y_angle_start,float xz_angle_count,float y_angle_count) {
        float xz_angle_end = xz_angle_start + xz_angle_count;
        float y_angle_end = y_angle_start + y_angle_count;
        if(xz_angle_start > xz_angle_end) {
            swap(xz_angle_start,xz_angle_end);
        }
        if(y_angle_start > y_angle_end) {
            swap(y_angle_start,y_angle_end);
        }
        
        List<Float> vertices = new ArrayList<Float>();
        for(float xz_angle = xz_angle_start;xz_angle <= (xz_angle_end - xz_span);xz_angle += xz_span) {
            for(float y_angle = y_angle_start;y_angle <= (y_angle_end - y_span);y_angle += y_span) {
                Float3 x0y0 = getVertex(xz_angle,y_angle);
                Float3 x1y0 = getVertex(xz_angle + xz_span,y_angle);
                Float3 x0y1 = getVertex(xz_angle,y_angle + y_span);
                Float3 x1y1 = getVertex(xz_angle + xz_span,y_angle + y_span);
                
                add_triangle_to_List(vertices,x0y0,x0y1,x1y0);
                add_triangle_to_List(vertices,x1y0,x0y1,x1y1);
            }
        }
        return toArray(vertices);
    }

法向量的话直接用顶点坐标就行了
所以如果你要用它做一些奇怪的形状(比如new Sphere(4,18)),会出现一些不合理的光照,但是非常平滑
至于为什么用18这个数…因为它是360的1/20…

圆柱体

生成顶点的两个函数

public static Float3 getVertex(float angle,float y) {
        float x = (float)Math.sin(Math.toRadians((float)angle)) * RADIUS;
        float z = (float)Math.cos(Math.toRadians((float)angle)) * RADIUS;
        return new Float3(x,y,z);
    }
public static float[] genVertices(float start,float count,float span) {
        float end = start + count;
        if(start > end) {
            swap(start,end);
        }
        
        final float upper = 0.5f;
        final float nether = -0.5f;
        Float3 upperCenter = new Float3(0,upper,0);
        Float3 netherCenter = new Float3(0,nether,0);
        
        List<Float> vertices = new ArrayList<Float>();
        for(float angle = start;angle <= (end - span);angle += span) {
            Float3 x0u = getVertex(angle,upper);
            Float3 x1u = getVertex(angle + span,upper);
            Float3 x0n = getVertex(angle,nether);
            Float3 x1n = getVertex(angle + span,nether);
            
            add_triangle_to_List(vertices,upperCenter,x0u,x1u);
            add_triangle_to_List(vertices,x0u,x0n,x1u);
            add_triangle_to_List(vertices,x1u,x0n,x1n);
            add_triangle_to_List(vertices,x0n,netherCenter,x1n);
        }
        return toArray(vertices);
    }

生成法向量的两个函数

public static Float3 getNormal(float angle) {
        float x = (float)Math.sin(Math.toRadians((float)angle));
        float z = (float)Math.cos(Math.toRadians((float)angle));
        return VectorUtil.normalize(new Float3(x,0,z));
    }
public static float[] genNormals(float start,float count,float span) {
    	float end = start + count;
        if(start > end) {
            swap(start,end);
        }
        
        final Float3 upper = new Float3(0,1,0);
        final Float3 nether = new Float3(0,-1,0);
        
        List<Float> normals = new ArrayList<Float>();
        for(float angle = start;angle <= (end - span);angle += span) {
            Float3 x0 = getNormal(angle);
            Float3 x1 = getNormal(angle + span);
            
            add_triangle_to_List(normals,upper,upper,upper);
            add_triangle_to_List(normals,x0,x0,x1);
            add_triangle_to_List(normals,x1,x0,x1);
            add_triangle_to_List(normals,nether,nether,nether);
        }
        return toArray(normals);
    }

胶囊

胶囊是用2个半圆和1个圆柱体拼起来的,很简单,就不做讲述了

SimpleGraphicsLibrary

这个是SGL的github,可以在SGL-1.2分支中找到完整源代码

效果图

一如既往地,给各位看看效果
p.s.由于着色器的问题,导致胶囊只旋转了顶点,没旋转法向量
都是时臣的错!(大雾)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值