着色器代码
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.由于着色器的问题,导致胶囊只旋转了顶点,没旋转法向量
都是时臣的错!(大雾)