1. 程式人生 > >【OpenGL程式設計】拖尾、刀光、劍光、尾焰效果的開發

【OpenGL程式設計】拖尾、刀光、劍光、尾焰效果的開發

重要

為了方便大家共同交流學習,我對模組進行了升級,現在為Version 2。Version 2版本按照Google C++程式設計規範修改了部分註釋和變數名稱,建議大家去我的GitHub去檢視,本文章的演算法部分還是可以借鑑的。改動具體如下。
1、新增詳細類註釋,概括類的功能。
2、修改了部分變數名稱。
3、 升級專案環境為Android Studio 3.2,原版本為2.2,已經淘汰。

說在開始

最近模擬了切水果裡面的拖尾效果,其可以應用在許多的場景裡面,例如,武器的刀光,飛機的尾焰效果等等。我開發的這個Demo是基於OpenGL ES的,開發環境(IDE)使用的Android Studio。如果想讓案例使用在其他平臺,還需要借鑑本節的演算法自己開發,如果是OpenGL或者OpenGL ES的話,直接就可以使用。(當然也需要適當的修改的)。

程式碼位置

我把我的Demo都放在我的github上,如果對您有幫助還希望您能幫我點一個star。https://github.com/ModestBean/MyStreak 謝謝。本人的知識有限,如果本節內容有錯誤和不合理之處,還請朋友們多多指出,我會虛心接受每一個建議。
##執行效果
這裡寫圖片描述
當然我觸控的方法都是基於Android的觸控寫的。

原理部分

其演算法與cocos的的MotionStreak類似。
OpenGL ES中有三種基本的圖元,點線和三角形。點主要用在粒子系統,最常用的就是三角形,我們看到的做工精美的3D模型就是很多三角形組成的,三角形的數量也就決定了模型的精細程度,因為在我們的需求裡用三角形就措措有餘了。
思路大體如下:
其實繪製的就是一個三角形帶。在平常的程式中,經常使用的繪製方式是GL_TRIANGLES,此繪製方式就是以三角形進行繪製。但是這裡使用的繪製方式是GL_TRIANGLE_STRIP,此繪製方式就是使用三角帶形式進行繪製。
其實可以發現,不管這種特效是跟著武器走還是跟著手指滑動走,都是動態改變的,這就說明我們需要動態去更新這個三角帶,不斷的向三角形帶中加入或者移除頂點。
頂點的移除有兩種方式:

  • 第一種是每個頂點都有個生存週期,過了生命週期的時間就會被移除
  • 第二種是規定一個頂點個數的上限,超過頂點個數就會被移除

如何生成三角形帶的頂點位置?

需要注意的是,我們不能直接將武器的軌道頂點或者手指滑動的位置直接拿過來使用,是需要去計算三角形帶頂點位置的。
演算法如下:

  • 取上一個頂點的位置,和當前頂點的位置形成一個二維向量V1,然後得到V1的垂直向量V2,三角形帶是有寬度width的,根據寬度width得到V2方向上的兩個頂點,將得到的頂點儲存起來。
    這裡寫圖片描述
  • 當然只有頂點是不夠的,還需要一幅紋理圖和對應紋理座標。紋理座標就很簡單了,t的值不是1就是0,而s的值需要切割成不同的段數。
    紋理圖如下
    這裡寫圖片描述

    紋理座標如下所示:
    這裡寫圖片描述
    當然頂點資料和紋理座標都是需要動態更新的,然後使用OpenGL ES的紋理就可以畫出來了。

程式碼部分

程式碼較長,我就簡單貼一下儲存控制引數的類吧。完整的Demo可以在我github上找到。

/**
 * Simple to Introduction
 * @Author          [蘇伊 [email protected]]
 * @Date            [2018-10-18]
 * @Description     [拖尾引數常量類]
 * @version         [2.0]
 */
public class StreakDataConstant {
    public static Object lock=new Object(); //資源鎖
    public static float STREAK_WIDTH=0.06f;//條帶的寬度
    public static int STREAK_MAX_NUMBER=30*2;//拖尾的最大長度(必須是2的倍數)
    public static int THREAD_DISAPPEAR_TIME=10;//拖尾的消失時間(手指離開後執行緒休息時間)
    public static float[] LINE_COLOR={1.0f,1.0f,0.0f,1.0f};//拖尾的顏色

    public static final float MAX_LIFE_SPAN= 1.5f; //最大生命週期
    public static final float LIFE_SPAN_STEP= 0.05f;//生命週期步進

    public static int SRC_BLEND= GLES30.GL_SRC_ALPHA;//源混合因子
    public static int DST_BLEND= GLES30.GL_ONE;//目標混合因子(得到背景全部顏色)
    public static int BLEND_FUNC= GLES30.GL_FUNC_ADD;//混合方式
}

註釋中說明的很清楚了就不多介紹了。
頂點著色器部分:

#version 300 es
uniform mat4 uMVPMatrix; //總變換矩陣
uniform float maxLifeSpan;//最大生命期
layout (location = 0) in vec3 aPosition;//頂點位置
in vec2 aTexCoor;//頂點紋理座標
out vec3 vPosition;//傳遞給片元著色器頂點位置和週期
out float sjFactor;//用於傳遞給片元著色器的總衰減因子
out vec2 vTextureCoord;//用於傳遞給片元著色器的變數
void main()
{
   gl_Position = uMVPMatrix * vec4(aPosition.xy,0,1); //根據總變換矩陣計算此次繪製此頂點位置
   vPosition=aPosition;//x,y,0,週期
   sjFactor=aPosition.z/maxLifeSpan;//計算總衰減因子,並將其傳遞給片元著色器
   vTextureCoord=aTexCoor;//將紋理座標傳給片元著色器
}

總衰減因子=當前生命週期/最大生命週期。當衰減因子達到極限值的時候,對應片元就會消失,這樣就實現了根據生命週期衰減的目的了。
片元著色器:

#version 300 es
precision mediump float;
uniform sampler2D sTexture;//紋理內容資料
uniform vec4 lineColor;//紋理內容資料

in vec3 vPosition;//接收x,y,0,週期
in float sjFactor;//接收衰減因子
in vec2 vTextureCoord;//用於傳遞給片元著色器的變數
out vec4 fragColor;//輸出到的片元顏色
void main()
{
   vec4 stColor=texture(sTexture, vTextureCoord);//取樣出紋理顏色
   fragColor=lineColor*sjFactor*stColor.a;//給此片元顏色值(線條顏色*衰減因子*Alpha值)
}

最終片元顏色需要乘以取樣出的紋理顏色的Alpha值,因為這裡的線條顏色是我自己自定義的,不是從紋理衝取樣出的顏色,紋理只提供“形狀”,這裡需要注意。

最後

本人的知識有限,如果本節內容有錯誤和不合理之處,還請朋友們多多指出,我會虛心接受每一個建議。

相關推薦

OpenGL程式設計效果開發

重要 為了方便大家共同交流學習,我對模組進行了升級,現在為Version 2。Version 2版本按照Google C++程式設計規範修改了部分註釋和變數名稱,建議大家去我的GitHub去檢視,本文章的演算法部分還是可以借鑑的。改動具體如下。 1、新增詳細類註

Java程式設計寫入讀取遍歷Properties檔案

在Java開發中通常我們會儲存配置引數資訊到屬性檔案。這種屬性檔案能夠是擁有鍵值對的屬性檔案,也能夠是XML檔案。關於XML檔案的操作,請參考博文【Java程式設計】DOM XML Parser 解析、遍歷、建立XML。 在該篇博文中,我將展示怎樣向屬性檔案寫入鍵值對。怎樣讀取屬性檔案

網路程式設計TCP網路程式設計中connect()listen()和accept()三者之間的關係

舉個簡單的例子(以下程式碼只是示範性的,用於說明不同套接字的作用,實際的函式會需要更多的引數): /* 建立用於監聽和接受客戶端連線請求的套接字 */ server_sock = socket(); /* 繫結監聽的IP地址和埠 */ bind(server_sock); /* 開始監聽 */ li

3網路程式設計Socket程式設計

一、Socket定義     Socket:在TCP/IP協議中,“IP地址+TCP或UDP埠號”唯 一標識網路通訊中的一個程序,所以“IP地址+埠號”就稱為socket。 在TCP協議中,建立連線的兩個程序各自有一個socket來標識,那麼這兩個socket組成的socket pair

2網路程式設計TCP報文段/網路位元組序/主機位元組序/網-主位元組序轉換函式

一、TCP報文段格式     TCP雖然是面向位元組流的,但TCP傳送的資料單元卻是報文段。一個TCP報文段分為首部和資料兩個部分。TCP報文段首部的前20個位元組是固定的,後面有4n位元組是根據需要增加的選項。TCP首部的最小長度是20位元組,最大長度是60位元組。

1網路程式設計Socket/TCP/UDP/HTTP/HTTPS/網路分層模型

一、簡介 1、相關概念     TCP:傳送控制協議(Transmission Control Protocol)     UDP:使用者資料報協議 (UDP:User Datagram Protocol)     HTTP:全稱是HyperText Transfer Pro

《瘋狂Java講義(第4版)》-----第11章AWT程式設計(AWT常用元件事件處理)

AWT常用元件 雖說是常用元件,如果不經常使用,還是比較陌生的!!!暫且根據書本列出來一些,先結合書上例項認識之,待之後結合實際案例選擇用之、研究之(參看官方API)! Button Canvas(用於繪圖的畫布) Checkbox CheckboxGroup(

JDBC程式設計Java 連線 MySQL資料庫基礎入門和進階

Content: 常用的JDBC API 資料庫環境的搭建 建立資料庫連線 資料庫訪問優化 一. 常用的JDBC API 1. DriverManager類 : 資料庫管理類,用於管理一組JDBC驅動程式的基本服務。應用程式和資料

併發程式設計對阻塞/非阻塞同步/非同步併發/並行等基本概念的理解

1. 併發與並行 併發:concurrency 並行:parallelism 開發過程中,常常會接觸併發有關的概念,比如併發計算(concurrent computing),併發系統( concurrent system),併發控制(concurrent

Socket程式設計篇五之IO同步非同步阻塞非阻塞

參考Richard Stevens的“UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking ”,6.2

Java程式設計DOM XML Parser解析遍歷建立XML

1、前言 DOM XML Parser介紹 DOM 是 W3C 處理 XML 的標準 API,它是許多其它與 XML 處理相關的標準的基礎,不僅是 Java,其它諸如 Javascript,PHP,MS .NET 等等語言都實現了該標準,成為了應用最為廣泛的 XML 處理方

4Shell 程式設計分支迴圈

一、分支 1、if if語句的語法格式: if condition then command1 command2 ... commandN fi 寫成一行(適用於終端命令提示符): if [ $(ps -ef | grep -c "s

6Shell 程式設計輸入/輸出重定向

大多數 UNIX 系統命令從你的終端接受輸入並將所產生的輸出傳送回到您的終端。一個命令通常從一個叫標準輸入的地方讀取輸入,預設情況下,這恰好是你的終端。同樣,一個命令通常將其輸出寫入到標準輸出,預設情況下,這也是你的終端。 重定向命令列表如下: 命令

Java程式設計foreach支援集合CollectionIterable遍歷原因分析

1、Collection、AbstractCollection、Iterable關係 Iterator是一個介面 public interface Iterator<E> { boolean hasNext(); E next();

網路程式設計之九事件選擇WSAEventSelect

WSAEventSelect模型是類似於WSAAsyncSelect模型的另一個有用的非同步I/O模型。它允許應用程式在一個或者多個套接字上接收以事件為基礎的網路事件。 在這裡,最主要的差別是在於網路事件會投遞到一個事件物件控制代碼。並不是投遞到一個視窗。 我們使用事件

Socket程式設計篇六之IO多路複用——selectpollepoll

在上一篇中,我簡單學習了 IO多路複用的基本概念,這裡我將初學其三種實現手段:select,poll,epoll。 I/O 多路複用是為了解決程序或執行緒阻塞到某個 I/O 系統呼叫而出現的技術,使程序或執行緒不阻塞於某個特定的 I/O 系統呼叫。 select()

網路程式設計socket程序的關係

1. Socket 的概念 埠是TCP/IP協議中的概念,描述的是TCP協議上層的應用(FTP,HTTP,SMTP…),在作業系統中,可以理解為基於TCP的系統服務或者說系統程序!如下圖,FTP就需要佔用特定的TCP埠。TCP/IP 協議棧的實現在系統層,HT

shell程式設計for迴圈while迴圈break跳出迴圈continue結束本次迴圈和exit退出整個指令碼

一、for迴圈  語法:for 變數名 in 條件; do …; done  案例1:  #!/bin/bash sum=0 for i in `seq 1 100` do     sum=$[$sum+$i]     echo $i done echo $sum 案

Java程式設計寫入讀取遍歷配置檔案 Properties類

在Java開發中通常我們會儲存配置引數資訊到屬性檔案,這樣的屬性檔案可以是擁有鍵值對的屬性檔案,也可以是XML檔案,關於XML檔案的操作,請參考博文【Java程式設計】DOM XML Parser 解析、遍歷、建立XML。在該篇博文中,我將展示如何向屬性檔案寫入鍵值對,如

併發程式設計Object的waitnotify和notifyAll方法

本部落格系列是學習併發程式設計過程中的記錄總結。由於文章比較多,寫的時間也比較散,所以我整理了個目錄貼(傳送門),方便查閱。 併發程式設計系列部落格傳送門 方法簡介 wait方法 wait方法是Object類中的一個方法。呼叫這個方法會讓呼叫執行緒進入waiting狀態,直到另一個執行緒呼叫了當前物件上的