Unity流水账14:GL、Graphics及CommandBuffer

一、GL
(1)、描述
  底层图形库。
  使用此类可以处理激活转换矩阵,发出类似于OpenGL立即模式的渲染命令以及执行其他低级图形任务。注意:在几乎所有情况下,使用Graphics.DrawMesh或CommandBuffer都比使用立即模式绘图更有效。
  GL立即绘图函数使用当前设置的"current material"(参见Material.SetPass)。材质控制渲染的完成方式(混合方式、使用纹理等),因此,除非你在使用GL绘制函数前将其显式设置为某种东西,否则材质可能是任何东西。另外,如果你从GL绘图代码中调用任何其他绘图命令,它们可以将材质设置为其他内容,因此也需要确保其也处于受控状态。
  GL绘图命令立即执行。这意味着,如果在Update()中调用它们,它们将在渲染照相机之前执行(并且照相机很可能会清除屏幕,从而使GL绘图不可见)。
  调用GL绘图的通常位置是在摄像机附带的脚本的OnPostRender()中或image effect函数(OnRenderImage)

using UnityEngine;

public class GLTest : MonoBehaviour
{
   
    //当添加物体时,从物体位置绘制彩色摄像
    public int lineCount = 100;
    public float radius = 3.0f;
    static Material lineMaterial;
    static void CreateLineMaterial()
    {
   
        if (!lineMaterial)
        {
   
            //unity具有内置的着色器,可用于绘制简单的彩色物体
            Shader shader = Shader.Find("Hidden/Internal-Colored");
            lineMaterial = new Material(shader);
            lineMaterial.hideFlags = HideFlags.HideAndDontSave;
            //开启透明度混合
            lineMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
            lineMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
            //关闭背面剔除
            lineMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
            //关闭深度写入
            lineMaterial.SetInt("_ZWrite", 0);
        }
    }
    //所有常规渲染完成后将被调用
    public void OnRenderObject()
    {
   
        CreateLineMaterial();
        //应用材质
        lineMaterial.SetPass(0);
        GL.PushMatrix();
        //设置用于绘制的变化矩阵以匹配我们的变换:将当前的模型矩阵设置为指定矩阵
        //用于将顶点从模型空间转到世界空间
        GL.MultMatrix(transform.localToWorldMatrix);
        //绘制lines
        GL.Begin(GL.LINES);
        for(int i = 0; i < lineCount; ++i)
        {
   
            float a = i / (float)lineCount;
            float angle = a * Mathf.PI * 2;
            //顶点颜色从红色到绿色
            GL.Color(new Color(a, 1 - a, 0, 0.8F));
            //在物体位置的顶点
            GL.Vertex3(0, 0, 0);
            //圆边上的另一个顶点
            GL.Vertex3(Mathf.Cos(angle) * radius, Mathf.Sin(angle) * radius, 0);
        }
        GL.End();
        GL.PopMatrix();
    }
}

显示结果
  Note:当你需要绘制几条线或三角形并且不想处理网格时,几乎总是使用此类。如果要避免意外,使用方式如下:

using UnityEngine;

public class GLTest : MonoBehaviour
{
   
    private void OnPostRender()
    {
   
        //设置你的材质
        GL.PushMatrix();
        //yourMaterial.SetPass();
        //画你的东西
        GL.PopMatrix();
    }
}

  Note:在画你的东西的位置,需要对先前声明的材质进行SetPass(),该材质将用于绘制。如果你不使用SetPass,那么你将无法确定当前使用哪个材质绘制。

(2)、Static Properties

invertCulling:选择是否反转背面剔除(true)或否(false);该标志可以“flip(翻转)”所有渲染对象的剔除模式。主要用例:为镜子、水等渲染反射。由于用于渲染反射的相机已为镜像,因此必须点到剔除顺序。你可以看到Effects标准包中的Water脚本如何执行此操作。
函数定义:public static bool invertCulling;
代码示例:
using UnityEngine;

//当附加到相机上时,此脚本将使所有渲染"从里到外"翻转,即将渲染对象的背面而不是正面
[ExecuteInEditMode]
public class GLTest : MonoBehaviour
{
   
    private bool oldCulling;
    public void OnPreRender()
    {
   
        oldCulling = GL.invertCulling;
        GL.invertCulling = true;
    }
    private void OnPostRender()
    {
   
        GL.invertCulling = oldCulling;
    }
}
LINE_STRIP:开始模式:绘制线条;从起点到终点在经过的每个顶点之间绘制线条。如果传递三个顶点A,B和C,则会绘制两条线:一条在A和B之间,一条在B和C之间。要设置2D绘图屏幕,使用GL.LoadOrho或GL.LoadPixelMatrix。要设置3D绘图屏幕,使用GL.LoadIdentity,然后使用GL.MultMatrix和所需的装换矩阵。
函数定义:public static int LINE_STRIP;
LINES:开始模式:绘制线段。在没对通过的顶点之间绘制线。如果传递四个顶点A,B,C和D,则会绘制两条线:一条在A和B之间,一条在C和D之间。要设置2D绘图屏幕,使用GL.LoadOrho或GL.LoadPixelMatrix。要设置3D绘图屏幕,使用GL.LoadIdentity,然后使用GL.MultMatrix和所需的装换矩阵。
函数定义:public static int LINES;
代码示例:
using UnityEngine;

public class GLTest : MonoBehaviour
{
   
    //从"start Vertex"变量到当前鼠标位置绘制一条线
    Material mat;
    Vector3 startVertex;
    Vector3 mousePos;
    private void Start()
    {
   
        startVertex = Vector3.zero;
    }
    private void Update()
    {
   
        mousePos = Input.mousePosition;
        //按空格键更新startVertex
        if (Input.GetKeyDown(KeyCode.Space))
        {
   
            startVertex = new Vector3(mousePos.x / Screen.width, mousePos.y / Screen.height, 0);
        }
    }
    private void OnPostRender()
    {
   
        if (!mat)
        {
   
            Shader shader = Shader.Find("Hidden/Internal-Colored");
            mat = new Material(shader);
        }
        GL.PushMatrix();
        mat.SetPass(0);
        GL.LoadOrtho();
        GL.Begin(GL.LINES);
        GL.Color(Color.red);
        GL.Vertex(startVertex);
        GL.Vertex(new Vector3(mousePos.x / Screen.width, mousePos.y / Screen.height, 0));
        GL.End();
        GL.PopMatrix();
    }
}

显示结果

modelview:当前的模型视图矩阵.分配给此变量等效于OpenGL中的glLoadMatrix(mat);在其他图形API中,也有相似功能。更改modelview矩阵会覆盖当前相机的视图参数,因此大多数情况下,你可以使用GL.PushMatrix和GL.PopMatrix保存和还原矩阵。读取此变量将返回当前的模型视图矩阵。
函数定义:public static Matrix4x4 modelview;
QUADS:开始模式:绘制四边形。使用每组传递的4个顶点绘制四边形。如果传递4个顶点,将绘制一个四边形,其中每个顶点称为四边形的一个角。如果传递8个顶点,将绘制2个四边形。要设置2D绘图屏幕,使用GL.LoadOrho或GL.LoadPixelMatrix。要设置3D绘图屏幕,使用GL.LoadIdentity,然后使用GL.MultMatrix和所需的装换矩阵。
代码示例:
using UnityEngine;

//在屏幕上绘制红色菱形,并在左上角绘制一个小的青色四边形
public class GLTest : MonoBehaviour
{
   
    Material mat;
    private void OnPostRender()
    {
   
        if (!mat)
        {
   
            Shader shader = Shader.Find("Hidden/Internal-Colored");
            mat = new Material(shader);
        }
        GL.PushMatrix();
        mat.SetPass(0);
        //0-1范围
        GL.LoadOrtho();
        GL.Begin(GL.QUADS);
        GL.Color(Color.red);
        GL.Vertex3(0, 0.5f, 0);
        GL.Vertex3(0.5f, 1, 0);
        GL.Vertex3(1, 0.5f, 0);
        GL.Vertex3(0.5f, 0, 0);
        GL.Color(Color.cyan);
        GL.Vertex3(0, 0, 0);
        GL.Vertex3(0, 0.25f, 0);
        GL.Vertex3(0.25f, 0.25f, 0);
        GL.Vertex3(0.25f, 0, 0);
        GL.End();
        GL.PopMatrix();
    }
}

显示结果

sRGBWrite:控制在渲染时是否执行线性到sRGB的颜色转换。仅当使用"Linear Color Space(线性颜色空间)"渲染时,此属性才有意义。通常,当使用线性颜色空间时,非HDR渲染纹理被视为sRGB数据("常规颜色"),而片段着色器的输出被视为线性颜色值。因此,默认情况下,片段着色器的颜色值将转换为sRGB。但是,如果你知道片段着色器由于某种原因已经输出了sRGB颜色值,并且想要关闭"Linear-to-sRGB(线性到sRGB)"写入颜色转换,则可以使用此属性来实现。注意:并非所有平台都支持关闭sRGB写入的功能(通常"tile based"的移动手机的GPU无法做到),因此这被认为是"不得已的功能"。最好使用适当的颜色空间标记(线性vs sRGB)创建RenderTextures,而不要在渲染过程中将转换切换到其中。
函数定义:public static bool sRGBWrite;
TRIANGLE_STRIP:开始模式:绘制三角形线条。从起点到终点在所传递的每个顶点之间绘制三角形。如果传递五个顶点A,B,C,D和E,则会绘制三个三角形。第一个三角形绘制在前三个顶点之间。所有后续三角形均使用前两个顶点,再加上下一个附加顶点。在此示例中,三个绘制的三角形将是A,B,C,然后是B,C,D,最后是C,D,E.要设置2D绘图屏幕,使用GL.LoadOrho或GL.LoadPixelMatrix。要设置3D绘图屏幕,使用GL.LoadIdentity,然后使用GL.MultMatrix和所需的装换矩阵。
函数定义:public static int TRIANGLE_STRIP;
代码示例:
using UnityEngine;

//在屏幕左侧绘制2个看起来像正方形的三角形
public class GLTest : MonoBehaviour
{
   
    Material mat;
    private void OnPostRender()
    {
   
        if (!mat)
        {
   
            Shader shader = Shader.Find("Hidden/Internal-Colored");
            mat = new Material(shader);
        }
        GL.PushMatrix();
        mat.SetPass(0);
        //0-1范围
        GL.LoadOrtho();
        GL.Begin(GL.TRIANGLE_STRIP);
        GL.Color(new Color(0,0,0,1));
        GL.Vertex3(0.25f, 0.5f, 0);
        GL.Vertex3(0, 0.5f, 0);
        GL.Vertex3(0.25f, 0.25f, 0);
        GL.Vertex3(0, 0.25f, 0);
        GL.End();
        GL.PopMatrix();
    }
}

显示结果

TRIANGLES:开始模式:绘制三角形。使用每组3个顶点绘制三角形。如果传递3个顶点,则将绘制一个三角形,其中每个顶点变为该三角形的一个角。如果传递6个顶点,将绘制2个三角形。
函数定义:public static int TRIANGLES;
代码示例:
using UnityEngine;

public class GLTest : MonoBehaviour
{
   
    Material mat;
    private void OnPostRender()
    {
   
        if (!mat)
        {
   
            Shader shader = Shader.Find("Hidden/Internal-Colored");
            mat = new Material(shader);
        }
        GL.PushMatrix();
        mat.SetPass(0);
        GL.LoadOrtho();
        GL.Begin(GL.TRIANGLES);
        GL.Vertex3(0, 0, 0);
        GL.Vertex3(1, 1, 0);
        GL.Vertex3(0, 1, 0);
        GL.End();
        GL.PopMatrix();
    }
}

显示结果

wireframe:是否应该在线框中进行渲染。启用线框模式将影响呼叫后渲染的所有对象,知道你重新关闭线框。在Unity编辑器中,线框模式始终在重现绘制任何窗口之前关闭。注意:某些平台(例如移动平台OpenGL ES)不支持线框渲染。
函数定义:public static bool wireframe;
代码示例:
using UnityEngine;

//将此脚本附加到相机,这将使其在线框中渲染
public class GLTest : MonoBehaviour
{
   
    private void OnPreRender()
    {
   
        GL.wireframe = true;
    }
    private void OnPostRender()
    {
   
        GL.wireframe = false;
    }
}

结果显示
(2)、Static Methods

Begin:开始绘制3D图元。在OpenGL中,它匹配glBegin;在其他图形API上,也有相应功能。在GL.Begin和GL.End之间,调用GL.Vertex,GL.Color,GL.TexCoord和其他即时模式绘制函数是有效的。
函数定义:public static void Begin(int mode)
函数参数:
mode:绘制图元:可以是TRIANGLES,TRIANGLE_STRIP,QUADS或LINES。
代码示例:
{
   
    Material mat;
    private void OnPostRender()
    {
   
        if (!mat)
        {
   
            Shader shader = Shader.Find("Hidden/Internal-Colored");
            mat = new Material(shader);
        }
        GL.PushMatrix();
        mat.SetPass(0);
        GL.LoadOrtho();
        GL.Begin(GL.TRIANGLES);  //三角形
        GL.Color(new Color(1, 1, 1, 1));
        GL.Vertex3(0.50f, 0.25f, 0);
        GL.Vertex3(0.25f, 0.25f, 0);
        GL.Vertex3(0.375f, 0.5f, 0);
        GL.End();
        GL.Begin(GL.QUADS);    //四边形
        GL.Color(new Color(0.5f, 0.5f, 0.5f, 1));
        GL.Vertex3(0.5f, 0.5f, 0);
        GL.Vertex3(0.5f, 0.75f, 0);
        GL.Vertex3(0.75f, 0.75f, 0);
        GL.Vertex3(0.75f, 0.5f, 0);
        GL.End();
        GL.Begin(GL.LINES);  //线段
        GL.Color(new Color(0, 0, 0, 1));
        GL.Vertex3(0, 0, 0);
        GL.Vertex3(0.75f, 0.75f, 0);
        GL.End();
        GL.PopMatrix();
    }
}

显示图片

Clear:清除当前渲染缓冲区。这将清除屏幕或你当前正在绘制的RenderTexture.在大多数情况下,某些摄像机正在某处绘制某些内容,并且可能已经使用天空盒的背景颜色清除了颜色缓冲区。清除区域受当前视口限制。此操作可能会更改模型/视图/投影矩阵。
函数定义:public static void Clear(bool clearDepth, bool clearColor, Color backgroundColor, float depth = 1.0f);
函数参数:
clearDepth:是否清除深度缓冲
clearColor:是否清除颜色缓冲
backgroundColor:如果clearColor为true,使用此颜色清除颜色缓冲区
depth:当clearDepth为true时,使用此深度值清除Z缓冲区的深度。有效范围是0(近平面)1(远平面)。该值与图形API无关:抽象层将转换该值以匹配当前使用的图形API
ClearWithSkybox:使用摄像机的天空盒清除当前渲染缓冲区。这会将天空盒绘制到屏幕或当前RenderTexture中。如果传递的相机没有自定义的Skybox组件,则将使用RenderSettings中的全局Skybox。
函数定义:public static void ClearWithSkybox(bool clearDepth, Camera camera)
函数参数:
clearDepth:是否清除深度缓冲区
camera:从此相机获取投影参数以及天空盒
Color:设置当前顶点颜色.在OpenGL中,相当于glColor4f(c.r,c.g,c.b,c.a);在其他图形API上,也有相似功能。
函数定义:public static void Color(Color c)
代码示例:
using UnityEngine;

//从屏幕的右下方到左上方绘制一条红线
//从屏幕的左下角到右上角的黄线
public class GLTest : MonoBehaviour
{
   
    Material mat;
    private void OnPostRender()
    {
   
        if (!mat)
        {
   
            Shader shader = Shader.Find("Hidden/Internal-Colored");
            mat = new Material(shader);
        }
        GL.PushMatrix();
        mat.SetPass(0);
        GL.LoadOrtho();
        GL.Begin(GL.LINES);
        GL.Color(Color.red);
        GL.Vertex3(1, 0, 0);
        GL.Vertex3(0, 1, 0);
        GL.Color(Color.yellow);
        GL.Vertex3(0, 0, 0);
        GL.Color(Color.blue);
        GL.Vertex3(1, 1, 0);
        GL.End();
        GL.PopMatrix();
    }
}

显示图片

End:结束绘制3D图元。在OpenGL中,它对应glEnd函数,在其他图形API中,也有相似功能。
函数定义:public static void End()
Flush:将驱动程序命令缓冲区中排队的命令发送到GPU.Direct3D 11是当前使用的图形API时,此函数对应ID3D11DeviceContext::Flush。当Direct3D 12是当前使用的图形API时,执行挂起的命令列表。当OpengGL是当前使用的图形API时,此调用将映射到glFlush.
GetGPUProjectionMatrix:根据相机的投影矩阵计算GPU投影矩阵。在Unity中,投影矩阵遵循OpenGL约定。但是,在某些平台上,必须对其进行一些转换以匹配本机API要求。使用此函数可以计算最终投影矩阵的样子。该值将与着色器中的UNITY_MATRIX_P矩阵匹配。如果打算使用此投影矩阵渲染RenderTexture,则renderIntoTexture值应设置为true.在某些平台上,它影响最终矩阵的外观。
函数定义:public static Matrix4x4 GetGPUProjectionMatrix(Matrix4x4 proj, bool renderIntoTexture);
函数参数:
proj: 源投影矩阵
renderIntoTexture:该投影将用于渲染到RenderTexture吗?
函数返回值:
Matrix4x4:为当前图形API调整的投影矩阵
InvalidateState:使内部缓存的呈现状态无效。这会使当前使用的图形API的所有缓存渲染状态无效。例如:如果(本机)插件更改了渲染状态设置,则必须调用此函数让Unity的渲染引擎意识到这一点。
函数定义:public static void InvalidateState();
IssuePluginEvent:将用户定义的事件发送到本机代码插件。如果平台和可用CPU的数量允许,则Unity中的渲染可以是多线程的。使用多线程渲染时,渲染API命令发生在与运行脚本的线程完全独立的线程上。因此,你的插件无法立即开始渲染,因为它可能会干扰渲染线程当前的操作。为了从插件进行任何渲染,可以从脚本中调用GL.IssuePluginEvent,这可以让渲染线程调用本机插件。例如,如果从摄像机的OnPostRender函数调用GL.IssuePluginEvent,则在摄像机完成渲染后会立即收到插件回调。回调必须是void UNITY_INTERFACE_API UnityRenderingEvent(int eventId)格式的函数。
函数定义:public static void IssuePluginEvent(IntPtr callback, int eventID);
函数参数:
eventID:用户定义的ID,以发送到回调
callback:Unity渲染器调用的本地回调队列
LoadIdentity:将单位矩阵加载到当前的模型视图矩阵。此功能会覆盖当前相机的视图参数,可以使用GL.PushMatrix和GL。PopMatrix保存和还原矩阵。
函数定义:public static void LoadIdentity();
LoadOrtho:辅助功能可以用于设置正交透视变换。调用LoadOrho之后,查看视椎从(0,0,-1)变为(1,1,100).LoadOrtho可用于以2D形式绘制图元。
函数定义:public static void LoadOrtho()
代码示例:
using UnityEngine;

//在已经绘制的三角形上绘制一个三角形
public class GLTest : MonoBehaviour
{
   
    Material mat;
    private void OnPostRender()
    {
   
        if (!mat)
        {
   
            Shader shader = Shader.Find("Hidden/Internal-Colored");
            mat = new Material(shader);
        }
        GL.PushMatrix();
        mat.SetPass(0);
        //原点在左下角,x轴与y轴的最大值是1
        GL.LoadOrtho();
        GL.Begin(GL.TRIANGLES);
        GL.Color(Color.red);
        GL.Vertex3(0f, 0f, 0);
        GL.Vertex3(0.25f, 0f, 0);
        GL.Vertex3(0f, 0.25f, 0);
        GL.End();
        GL.Begin(GL.TRIANGLES);
        GL.Color(Color.yellow);
        GL.Vertex3(0f, 0f, 1);
        GL.Vertex3(0.25f, 0f, -1);
        GL.Vertex3(0f, 0.25f, -1);
        GL.End();
        GL.PopMatrix();
    }
}

显示图片

LoadPixelMatrix:设置矩阵(MVP)让像素能正确渲染。
函数定义:
public static void LoadPixelMatrix():这将设置模型视图和投影矩阵,以便X,Y坐标直接映射到像素。(0,0)在当前摄像机视口的左下角,Z坐标从-1+1
public static void LoadPixelMatrix(float left, float right, float bottom, float top):这将设置模型视图和投影矩阵,以便X,Y坐标直接映射到像素。(左、底部在当前摄像机的视口的左下角;(右上)在当前摄像机的视口的右上角。Z坐标从-1+1)。此功能会覆盖当前相机的参数,因此大多数情况下,可以使用GL.PushMatrix和GL.PopMatrix保存和还原矩阵。
代码示例:
using UnityEngine;

//在观察坐标系绘制红色三角形
public class GLTest : MonoBehaviour
{
   
    Material mat;
    private void OnPostRender()
    {
   
        if (!mat)
        {
   
            Shader shader = Shader.Find("Hidden/Internal-Colored");
            mat = new Material(shader);
        }
        GL.PushMatrix();
        mat.SetPass(0);
        //MVP:屏幕空间
        GL.LoadPixelMatrix();
        GL.Begin(GL.TRIANGLES);
        GL.Color(Color.red);
        GL.Vertex3(0f, 0f, 0);
        GL.Vertex3(0f, Screen.height / 2, 0);
        GL.Vertex3(Screen.width / 2, Screen.height / 2, 0);
        GL.End();
        GL.Begin(GL.TRIANGLES);
        GL.Color(Color.red);
        GL.Vertex3(Screen.width, Screen.height, 0);
        GL.Vertex3(Screen.width, Screen.height / 2, 0);
        GL.Vertex3(Screen.width / 2, Screen.height / 2, 0);
        GL.End();
        GL.PopMatrix();
    }
}

结果显示

LoadProjectionMatrix:将任意矩阵加载到当前的投影矩阵(P).此功能会覆盖当前相机的参数,因此大多数情况下,可以使用GL.PushMatrix和GL.PopMatrix保存和还原矩阵。
函数定义:public static void LoadProjectionMatrix(Matrix4x4 mat)
代码示例:
using UnityEngine;

//在观察坐标系绘制红色三角形
public class GLTest : MonoBehaviour
{
   
    Matrix4x4 projMtrx = Matrix4x4.identity;
    Material mat;
    private void OnPostRender()
    {
   
        if (!mat)
        {
   
            Shader shader = Shader.Find("Hidden/Internal-Colored");
            mat = new Material(shader);
        }
        GL.PushMatrix();
        mat.SetPass(0);
        //P:裁剪空间
        GL.LoadProjectionMatrix(projMtrx);
        GL.Begin(GL.TRIANGLES);
        GL.Color(Color.red);
        //由于是单位矩阵,故Matrix4x4.identity * Vector3 = Vecto3可得裁剪空间坐标
        //然后根据(clip.x / (2 * clip.w) + 1/2) * pixelWidth可得屏幕坐标
        GL.Vertex3(-1f, -1f, 0);
        GL.Vertex3(-1f, 0f, 0);
        GL.Vertex3(0f, -1f, 0);
        GL.End();
        GL.PopMatrix();
    }
}

显示结果

MultiTexCoord:将当前纹理坐标(v.x, v.y, v.z)设置为实际纹理单位.在OpenGL中,如果可以使用多种纹理,可调用glMultiTexCoord与给定的纹理单位匹配。在其他图形API上,也有此类似功能。Z坐标仅在以下情况下使用:1.访问一个立方体贴图(使用矢量坐标来访问,因此为x,y&z). 2.进行"projective texturing(纹理投影映射)",需使用x和y坐标除以z得到最终坐标。反射水等功能会用到。该函数只能在GL.Begin和GL.End函数之间调用。
函数定义:public static void MultiTexCoord(int unit, Vector3 v);
代码示例:
using UnityEngine;

//在按下空格键是分配给材质的两个纹理之间的变化
public class GLTest : MonoBehaviour
{
   
    Material mat;
    bool flagTex = true;
    private void Update()
    {
   
        if(Input.GetKeyDown(KeyCode.Space))
        {
   
            if (flagTex)
                flagTex = false;
            else
                flagTex = true;
        }
    }
    private void OnPostRender()
    {
   
        if (!mat)
        {
   
            Debug.LogError("Please Assign a material on the inspector");
            return;
        }
        GL.PushMatrix();
        mat.SetPass(0);
        GL.LoadOrtho();
        GL.Begin(GL.QUADS);
        if (flagTex)
        {
   
            GL.MultiTexCoord(0, new Vector3(0, 0, 0)); //main texture
        }
        else
        {
   
            GL.MultiTexCoord(1, new Vector3(0, 0, 0)); //second texture
        }
        GL.Vertex3(0.25f, 0.25f, 0);
        if (flagTex)
        {
   
            GL.MultiTexCoord(0, new Vector3(0, 1, 0));
        }
        else
        {
   
            GL.MultiTexCoord(1, new Vector3(0, 1, 0));
        }
        
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值