寫個自研的圖文混排(一)

系列前言

應某些騰訊群友的需求,準備寫個自研 的圖文混排系列。有個技術QQ群544507409,歡迎水友前來交流

我是準備從零開始,僅僅基於Unity的MeshRender+MeshFilter這對基友來寫UI,雖然有部分代碼可能來自NGUI,不過也只是為了參考。

本篇文章主要還是講下我這個系列的具體思路。

基礎篇:一些2D的基礎概念,以及MeshRender+MeshFilter的具體使用

中級篇:顯示圖片和文字

高級篇:混合排列文字和圖片,並且讓圖片動起來

理論基礎

我還是先上我之前的一篇文章的鏈接Unity3D如何將圖片以正確的像素顯示在屏幕上。文章具體解決了"如何讓圖片按照1像素對應1屏幕解析度的顯示在屏幕上"的問題,其中萌新看得最模糊的,可能就是MeshRender跟MeshFilter兩個組件填值得問題。

這裡就著代碼講一下,MeshRender這個組件其實負責跟材質球打交道,MeshFilter負責跟Mesh頂點數據打交道。關於材質球和Mesh頂點數組,我打個比方:一個畫師用電腦畫一幅畫,首先他要準備好畫板、畫筆、電腦、電腦要裝好對於的畫圖軟體(POTHO SHOP之類的),然後他要把畫的點線面勾出來。也就是兩個東西:畫畫的前預準備的工具,具體畫出來的點線面,對應材質球和Mesh頂點數據。

具體的深入學習,關於材質球可以學習學習Unity Shader,以及關於Mesh頂點數據,可以去看看3D建模。

如果實在很萌新,我也就只好推薦淺墨大佬的書(淺墨的遊戲編程),逐夢旅程 WINDOWS遊戲編程之從零開始的第三篇,如下的內容。

第10章 快到碗里來——DirectX大局觀認知. 275

第11章 三維內功心法——Direct3D編程基礎. 301

第12章 騰飛前的助跑——Direct3D 繪製基礎. 338

第13章 邁向三維世界——Direct3D 的四大變換 372

第14章 繪製出質感的世界—光照與材質 390

第15章 做遊戲的主人——輸出控制利器DirectInput 421

第16章 起舞不落幕——與紋理映射的華麗邂逅. 452

(PS理論基礎的最後,我個人給一些大佬天天說的DrawCall的下個狹義的定義:Unity的一次DrawCall對應一個MeshRender。

兩種特殊情況,

一:如果MeshRender開啟了Dynamic Batch,那麼相同材質球(shareMaterial一樣)的MeshFilter會合併相對數量的頂點,然後使用同一個MeshRender。

二:開啟一個相機也會增加DrawCall。有大佬看見,麻煩告知下,相機的DrawCall在渲染層的意義到底是啥。)

看完你就差不多對這兩個組件有個大概的認識,OK我們開始搞事情。

上機實驗

實驗1-1:利用Unity,不使用貼圖並按照正確的像素比,在解析度為512*512的範圍顯示一張512* 512的純黑色圖片。

實現思路,1、構造一個frag著色器返回值為黑色的材質球,2、構造長寬為512*512的4個圖片頂點。

Shader代碼如下:

Shader "Unlit/Transparent Colored"n{ntPropertiesnt{ntt_MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}nt}ntntSubShadernt{nttLOD 200nnttTagsntt{nttt"Queue" = "Transparent"nttt"IgnoreProjector" = "True"nttt"RenderType" = "Transparent"ntt}nttnttPassntt{ntttCull OffntttLighting OffntttZWrite OnntttFog { Mode Off }ntttOffset -1, -1ntttBlend SrcAlpha OneMinusSrcAlphanntttCGPROGRAMnttt#pragma vertex vertnttt#pragma fragment fragtttnttt#include "UnityCG.cginc"nntttsampler2D _MainTex;ntttfloat4 _MainTex_ST;ntntttstruct appdata_tnttt{nttttfloat4 vertex : POSITION;nttttfloat2 texcoord : TEXCOORD0;nttttfixed4 color : COLOR;nttt};ntntttstruct v2fnttt{nttttfloat4 vertex : SV_POSITION;nttt};ntntttv2f o;nntttv2f vert (appdata_t v)nttt{ntttto.vertex = mul(UNITY_MATRIX_MVP, v.vertex);nttttreturn o;nttt}nttttntttfixed4 frag (v2f IN) : COLORnttt{nttttreturn float4(0,0,0,1);nttt}ntttENDCGntt}nt}nnt//備胎設為Unity自帶的普通漫反射 n Fallback" Diffuse " n}n

構造512*512的c#代碼如下

/*n ######### n ############ n ############# n ## ########### n ### ###### ##### n ### ####### #### n ### ########## #### n #### ########### #### n #### ########### ##### n ##### ### ######## ##### n ##### ### ######## ###### n ###### ### ########### ###### n ###### #### ############## ###### n ####### ##################### ###### n ####### ###################### ###### n ####### ###### ################# ###### n ####### ###### ###### ######### ###### n ####### ## ###### ###### ###### n ####### ###### ##### ##### n ###### ##### ##### #### n ##### #### ##### ### n ##### ### ### # n ### ### ### n ## ### ### n__________#_______####_______####______________nn 我們的未來沒有BUG n* ==============================================================================n* Filename: Black.csn* Created: 2017/11/11 15:51:28n* Author: To Hard The Mindn* Purpose: n* ==============================================================================n*/nusing System;nusing System.Collections.Generic;nusing UnityEngine;nnpublic class Black : MonoBehaviour {n public int width = 512;n public int height = 512;n public Color color = Color.black;nn private MeshFilter meshFilter;n private MeshRenderer meshRenderer;nn void Start() {n Shader s = Shader.Find("Unlit/Transparent Colored");n Material spriteMaterial = new Material(s);nn //得到MeshFilter對象// n meshFilter = gameObject.GetComponent<MeshFilter>();n meshRenderer = null;n if (meshFilter == null) {n //為null時,自動添加// n meshFilter = gameObject.AddComponent<MeshFilter>();n meshRenderer = gameObject.AddComponent<MeshRenderer>();n meshRenderer.sharedMaterial = spriteMaterial;n }n Fill();n }nn void Fill() {n //得到對應的網格對象// n Mesh mesh = new Mesh();n meshFilter.mesh = mesh;nn //三角形頂點的坐標數組// n Vector3[] vertices = new Vector3[4];n //三角形頂點數組// n int[] triangles = new int[6];n //顏色數組//n Color[] colors = new Color[4];n //uv貼圖坐標//n Vector2[] uv = new Vector2[4];nn float glWidth = (float)width / 2;n float glHeight = (float)height / 2;n //以當前對象的中心坐標為標準// n vertices[0] = new Vector3(-glWidth, -glHeight, 0);n vertices[1] = new Vector3(-glWidth, glHeight, 0);n vertices[2] = new Vector3(glWidth, -glHeight, 0);n vertices[3] = new Vector3(glWidth, glHeight, 0);nn //綁定頂點順序// n triangles[0] = 0;n triangles[1] = 2;n triangles[2] = 1;n triangles[3] = 2;n triangles[4] = 3;n triangles[5] = 1;nn //設置頂點顏色//n colors[0] = color;n colors[1] = color;n colors[2] = color;n colors[3] = color;nn //綁定貼圖UV//n uv[0] = new Vector2(0, 0);n uv[1] = new Vector2(0, 1);n uv[2] = new Vector2(1, 0);n uv[3] = new Vector2(1, 1);nn //給mesh賦值//n mesh.vertices = vertices;n mesh.triangles = triangles;n mesh.colors = colors;n mesh.uv = uv;n }n}n

運行起來的效果如圖1(一片非洲大陸(╯‵□′)╯︵┻━┻)

圖1

細心的同學一定發現,width、height、color,這3個值我想在運行的時候,調整他們,並且能看到變化。

實驗1-2,在運行的時候調整運行參數並看到表現效果

思路:Shader 調整下,利用頂點色來控制片元 顏色返回值,利用腳本的OnValidate方法,重新組織數據並繪製。

Shader關鍵代碼

v2f vert (appdata_t v)n{n o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);n o.color = v.color;n return o;n}nttttnfixed4 frag (v2f IN) : COLORn{n return IN.color;n}n

c# 關鍵代碼

void OnValidate() {n if (meshFilter && Application.isPlaying) {n Fill();n }n }n

成功脫非入歐((?′▽`)??)

最後貼上代碼的github 地址 ElPsyCongree/Emoji


推薦閱讀:

[OpenGL]Windows上OpenGL開發環境搭建
如何判斷線段和圓弧是否相交?
shadertoy 這個網站如何玩?
藝術抽象科學,科學證明藝術。-- Spacetime optimization與迪斯尼的動畫12法則的聯繫
簡述47種Shader Map的渲染原理與製作方法

TAG:计算机图形学 | Unity游戏引擎 |