一个莫比乌斯带的shader,效果如下:

Java类为GlMobiusRender,完整源码如下:

package com.opengl.learn.aric;import android.content.Context;
import android.opengl.GLES32;
import android.opengl.GLSurfaceView;
import android.util.Log;import com.opengl.learn.OpenGLUtils;
import com.opengl.learn.R;import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;import static android.opengl.GLES20.GL_ARRAY_BUFFER;
import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
import static android.opengl.GLES20.GL_DEPTH_BUFFER_BIT;
import static android.opengl.GLES20.GL_DEPTH_TEST;
import static android.opengl.GLES20.GL_FLOAT;
import static android.opengl.GLES20.GL_STATIC_DRAW;
import static android.opengl.GLES20.GL_TEXTURE0;
import static android.opengl.GLES20.GL_TEXTURE1;
import static android.opengl.GLES20.GL_TEXTURE_2D;
import static android.opengl.GLES20.GL_TRIANGLES;
import static android.opengl.GLES20.glGenBuffers;
import static android.opengl.GLES20.glGetUniformLocation;public class GlMobiusRender implements GLSurfaceView.Renderer {private static final String TAG = GlMobiusRender.class.getSimpleName();private final float[] mVerticesData ={-1.0f, 1.0f, 0.0f,-1.0f, -1.0f, 0.0f,1.0f, -1.0f, 0.0f,1.0f, -1.0f, 0.0f,1.0f, 1.0f, 0.0f,-1.0f, 1.0f, 0.0f,};private static final int BYTES_PER_FLOAT = 4;private static final int POSITION_COMPONENT_COUNT = 3;private Context mContext;private FloatBuffer mVerticesBuffer;private int mProgramObject, mVAO, mVBO, iTime, iResolution;private int mWidth, mHeight;private long startTime;public GlMobiusRender(Context context) {mContext = context;mVerticesBuffer = ByteBuffer.allocateDirect(mVerticesData.length * BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();mVerticesBuffer.put(mVerticesData).position(0);}@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {mProgramObject = OpenGLUtils.loadProgram(mContext, R.raw.glsea_vertex, R.raw.glmobius_fragment);iTime = glGetUniformLocation(mProgramObject, "iTime");iResolution = glGetUniformLocation(mProgramObject, "iResolution");int[] array = new int[1];GLES32.glGenVertexArrays(array.length, array, 0);mVAO = array[0];array = new int[1];glGenBuffers(array.length, array, 0);mVBO = array[0];Log.e(TAG, "onSurfaceCreated, " + mProgramObject + ", uTime: " + iTime + ", uResolution: " + iResolution);GLES32.glBindVertexArray(mVAO);mVerticesBuffer.position(0);GLES32.glBindBuffer(GL_ARRAY_BUFFER, mVBO);GLES32.glBufferData(GL_ARRAY_BUFFER, BYTES_PER_FLOAT * mVerticesData.length, mVerticesBuffer, GL_STATIC_DRAW);GLES32.glVertexAttribPointer(0, POSITION_COMPONENT_COUNT, GL_FLOAT, false, 0, 0);GLES32.glEnableVertexAttribArray(0);}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {mWidth = width;mHeight = height;}@Overridepublic void onDrawFrame(GL10 gl) {long now = System.currentTimeMillis();if (startTime == 0) {startTime = now;}float time = (now - startTime) / 1000f;GLES32.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);GLES32.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);GLES32.glEnable(GL_DEPTH_TEST);GLES32.glUseProgram(mProgramObject);GLES32.glUniform1f(iTime, time);GLES32.glUniform2f(iResolution, mWidth, mHeight);GLES32.glEnableVertexAttribArray(0);GLES32.glBindVertexArray(mVAO);GLES32.glDrawArrays(GL_TRIANGLES, 0, mVerticesData.length);GLES32.glBindVertexArray(0);GLES32.glDisableVertexAttribArray(0);}
}

顶点着色器和上一节完全相同,片段着色器完整源码如下:

// Created by Vinicius Graciano Santos - vgs/2014
// Based on the following article:
// http://data.imaginary-exhibition.com/IMAGINARY-Moebiusband-Stephan-Klaus.pdf#version 320 es
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif#define EPS 0.01
#define STEPS 64
#define TAU 6.28318530718// comment to stop the rotation.
#define ROTATION// comment to stop the homotopy between the mobius strip and the torus.
#define HOMOTOPYout vec4 FragColor;
uniform float iTime;
uniform vec2 iResolution;float mobius(vec3 p, float b) {float x = p.x, y = p.y, z = p.z;float xx = x*x, yy = y*y, zz = z*z, y3 = yy*y, x3 = xx*x;float xy = xx+yy, b2 = b*2.0, zxy = z*(xx*y*3.0-y3), xyy = x*yy*3.0-x3;float k1 = (2.0*zxy+xyy*(xy-zz+1.0))*(b-0.1)-xy*xy*(b2+0.2);float k2 = b*xy*0.2+(b2-0.2)*(zxy+xyy)-xy*(b+0.1)*(xy+zz+1.0);return k1*k1-xy*k2*k2;
}vec3 grad(vec3 p, float b) {vec2 q = vec2(0.0, EPS);return vec3(mobius(p+q.yxx, b) - mobius(p-q.yxx, b),mobius(p+q.xyx, b) - mobius(p-q.xyx, b),mobius(p+q.xxy, b) - mobius(p-q.xxy, b));
}float torus(vec3 p) {vec2 t = vec2(1.0, 0.32);vec2 q = vec2(length(p.xy)-t.x, p.z);return length(q)-t.y;
}mat3 rotY(float ang) {float c = cos(ang), s = sin(ang);return mat3(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
}mat3 rotX(float ang) {float c = cos(ang), s = sin(ang);return mat3(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
}vec3 shade(vec3 p, vec3 rd, float b, mat3 m) {vec3 col = vec3(0.0);vec3 n = normalize(-grad(p, b));// materialvec3  amb = vec3(0.05375, 0.05, 0.06625);vec3  dif = vec3(0.18275, 0.17, 0.22525);vec3  spe = vec3(0.332741, 0.328634, 0.346435);float shin = 39.4;// key lightvec3 l = normalize(m*vec3(1.0));vec3 h = normalize(l-rd);float lambert = max(0.0, dot(n, l));float blinn = lambert > 0.0 ? pow(max(0.0, dot(n, h)), shin) : 0.0;col += vec3(3.0, 2.0, 3.0)*(0.4*dif*lambert + 1.4*spe*blinn + 0.1*amb);// fill lightlambert = max(0.0, dot(n, -rd));blinn = lambert > 0.0 ? pow(lambert, shin) : 0.0;col += vec3(1.0)*(0.4*dif*lambert + 1.4*spe*blinn + 0.1*amb);// rim lightcol += 2.25*pow(clamp(1.0+dot(n, rd), 0.0, 1.0), 3.0);return col/(col+1.0);// reinhard
}float animCurve(in float t) {t = mod(iTime, 15.0);float f1 = smoothstep(5.0, 7.0, t);float f2 = 1.0-smoothstep(7.0, 9.0, t);return 0.01+0.09*f1*f2;
}void main(void) {vec2 fc = gl_FragCoord.xy / iResolution.xy;vec2 uv = -1.0+2.0*fc;uv.x *= iResolution.x/iResolution.y;vec2 mouse = 0.5*TAU*(-1.0/iResolution.xy);#ifndef HOMOTOPYfloat b = 0.01;#elsefloat b = animCurve(iTime);#endif#ifdef ROTATIONmouse.x += 0.3*iTime;#endifmat3 m = rotY(mouse.x)*rotX(mouse.y);vec3 ro = m*vec3(0.0, 0.0, 1.8);vec3 rd = m*normalize(vec3(uv, -1.0));float d = 10.0, t1 = 0.0;vec3 p = ro, col = vec3(1.0);// sphere-trace to torus envelope.for (int i = 0; i < STEPS; ++i) {if (d < EPS || t1 > 4.0) continue;d = torus(p);t1 += d; p = ro + t1*rd;}if (d < EPS) {// forward march to find root interval.float t2 = t1; d = mobius(p, b);for (int i = 0; i < 2*STEPS; ++i) {if (d > 0.0) continue;d = mobius(p, b);t2 += 2.0*EPS; p = ro + t2*rd;}// bisect towards root.if (d > 0.0) {for (int i = 0; i < 12; ++i) {d = 0.5*(t1+t2); p = ro + d*rd;if (mobius(p, b) > 0.0) t2 = d; else t1 = d;}col = shade(ro+d*rd, rd, b, m);}}// post-processingcol = smoothstep(0.0, 1.0, col);col *= 0.5 + 0.5*pow(25.0*fc.x*(1.0-fc.x)*fc.y*(1.0-fc.y), 0.45);col = pow(col, vec3(1.0/2.2));FragColor = vec4(col, 1.0);
}

当前记录的这些shader都是从Shadertoy上看到的,我们还未学习到其效果的神髓,后期必须要针对每个效果慢慢琢磨透其中的原理,最终的结果就是我们能理解片段着色器中每一行代码的含义及其实现后的效果,那时候我们才算学会了。

继续努力!!

Opengl ES系列学习--莫比乌斯带相关推荐

  1. Opengl ES系列学习--顶点属性、顶点数组和缓冲区对象

    本节我们继续来看一下<OPENGL ES 3.0编程指南 原书第2版(中文版)>书中第6章的内容,PDF下载地址:OPENGL ES 3.0编程指南 原书第2版(中文版),代码下载地址:O ...

  2. Opengl ES系列学习--顶点着色器

    本节我们继续来看一下<OPENGL ES 3.0编程指南 原书第2版(中文版)>书中第8章的内容,PDF下载地址:OPENGL ES 3.0编程指南 原书第2版(中文版),代码下载地址:O ...

  3. Opengl ES系列学习--glViewport API使用

    去年有分析了一些Opengl ES的实例,但是后面在实际的工作中,发现根基不牢,工作中使用的一些复杂场景还是理解的不够透彻,所以回过心来,必须把基础把扎实.从这节开始,我们后面对一些非常基础普通的Op ...

  4. Opengl ES系列学习--颜色

    本节我们来学习一下颜色的知识,在看完原作者讲解的颜色的知识的基础上,只要我们理解了,应该就能提取出重点,其实本节的重点就是下面这一句话. 所以我们要作的就是计算出物体颜色和光源颜色,然后把它们两个相乘 ...

  5. Opengl ES系列学习--太阳

    继续积累Shadertoy,大家也可去Shader女神的CSDN逛逛:Shader女神.使用别人写好的shader实现的一个太阳的效果,太漂亮了!!! 该效果实现是GlSunRender类,完整源码如 ...

  6. 《Android 3D游戏开发技术宝典——OpenGL ES 2.0》——2.3节手机自带数据库——SQLite...

    本节书摘来自异步社区<Android 3D游戏开发技术宝典--OpenGL ES 2.0>一书中的第2章,第2.3节手机自带数据库--SQLite,作者 吴亚峰,更多章节内容可以访问云栖社 ...

  7. EGL接口介绍-----Android OpenGL ES底层开发

    引自:http://www.cnitblog.com/zouzheng/archive/2011/05/30/74326.html EGL 是 OpenGL ES 和底层 Native 平台视窗系统之 ...

  8. OpenGL ES着色器语言之变量和数据类型

    所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符.变量在声明的时候首先要标明类型,后边可以跟多个变量,之间用逗号隔开.很多情 ...

  9. OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)...

    OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...

最新文章

  1. 洪小文:以科学的方式赤裸裸地剖析人工智能
  2. LiveVideoStack主编观察03 /大会见闻思考
  3. 黑客大佬:我是如何让50个文件一起骗过AI安防系统的?
  4. html div如何列对其,CSS:自适应N列布局如何解决两端对齐
  5. Qt学习笔记-简单的UDP广播包聊天室
  6. Java的String理解
  7. 力扣(leetcode)66.加一——c语言新手入门
  8. word2016标题序号变黑色竖线解决方法
  9. 【华为云技术分享】快速搭建网站之云速建站
  10. 用python做一个随机题目生成器
  11. 素材网下载图片要 VIP ? 不存在的
  12. kafka flush
  13. Python制作桑基图
  14. ANSYS Electronic各类
  15. hdu 4394 Digital Square【标准DFS】
  16. 2021-2025年中国物理疗法电子病历和计费软件行业市场供需与战略研究报告
  17. N以内双素数 马蹄集
  18. PDF控件PDFToolkit VCL V5.0.0.612发布 | 修复了PDF查看器和打印机
  19. 量化交易 聚宽 止盈止损策略
  20. 金蝶云星空采购订单套打模板明细表里相同编码取最小交货日期

热门文章

  1. 指令集CEO潘爱民受聘为之江实验室智能计算数字反应堆首席架构师
  2. 员工考勤管理系统html,一种员工考勤管理系统的制作方法
  3. 2021年R1快开门式压力容器操作考试技巧及R1快开门式压力容器操作证考试
  4. 韩国美女黑客是怎样的一种存在?
  5. 『无欲则无求』Linux系统管理 — 81、Linux进程的查看(ps命令)
  6. 从零开始一键安装TeslaMate
  7. Java-九九加法表
  8. DICOM:基于fo-dicom的简易DICOM Viewer
  9. DLNA - 一个伟大的方式来享受流媒体电影在首页
  10. 2.4万余门课程在线学,22家平台面向全国高校开放