渲染世界的OPENGL<15>纹理进阶-点精灵

本文详细介绍了OpenGL中的点精灵技术,包括如何使用点精灵显示2D纹理、微粒系统的应用、点的大小设置、代码实现、点参数调整、异形点的创建以及点的旋转。点精灵通过单个3D顶点渲染2D纹理,减少了带宽需求,简化了渲染过程。通过调整点的大小、形状和旋转,可以实现各种视觉效果。
摘要由CSDN通过智能技术生成

点精灵(Point Sprite)使用点精灵我们可以通过绘制一个3D点将一个2D纹理图像显示在任意位置上。
点精灵最常见的应用就是微粒系统。我们可以用点来表示在屏幕上移动的大量微粒,来产生一些视觉效果。但是把这些点表示为很小的重叠2D图像就是戏剧性流动着的细丝。
点精灵允许我们通过发送单个3D顶点,渲染一个完美对齐的纹理2D多边形。点精灵所需要的带宽只有为四边形发送四个顶点所用的带宽的四分之一,并且不需要客户端的矩阵逻辑来保持3D四边形和照相机的对齐。

(1)使用点
在客户端我们要做的只是简单绑定一个2D纹理,并且为纹理单元设置恰当的统一值。因为现在点精灵已经是默认的点光栅化模式。一种情况下例外:开启点平滑的时候。
我们不能使用点精灵和抗锯齿点。在片段程序中,有一个内建变量gl_PointCoord,这是一个分量向量,在顶点上对纹理坐标进行插值。

#version 130

out vec4 vFragColor;

in vec4 vStarColor;

uniform sampler2D  starImage;

void main(void)
    { 
    vFragColor = texture(starImage, gl_PointCoord) * vStarColor;
    }

如上面的片段着色器代码,对于点精灵来说,不需要将纹理坐标作为属性进行传递。
一个点就是一个单独的顶点,那么我们就不能以任何其他方式在点表面上进行插值了。当然如果我们无论如何都要提供一个纹理坐标,或者以自定义的方法进行插值,那么也没什么。

(2)点的大小

两种方式可以设置点的大小。


//第一种方式:
void glPointSize(FLfloat size);

这个函数为锯齿点以及抗锯齿点设置点的直径,以像素为单位。我们也可以在顶点着色器中用程序设置点大小:

//第二种方式
//首先启用点大小模式:
glEnable(GL_PROGRAM_POINT_SIZE);

然后在我们的顶点程序中,可以设置一个内建变量gl_PointSize,这个变量确定了点的最终光栅化大小。这种方式的一种常见用途就是根据点的距离来确定点的大小。当我们使用glPointSize函数设置点的代销的时候,他们不受到透视除法的影响,而是将所有点设置为相同大小。无论他们有多远。
关于点距离变换如下公式:

这里写图片描述

d为从这个点到观察点的距离,而a,b,c是二次方程的参数。我们可以将他们存储为统一值,并且应用程序来对他们进行更新,或者我们已经想好了一组特定的参数,也可以在顶点着色器中将他们设置为常量。
比如:我们想设置一个常量大小值,那么就将a设置为非0值,而将b,c设置为0。
如果a,c为0,b非0,那么点大小将随着距离变化而线性变化。
如果a,b设置为0,而c设置为非0。那么点大小将随着距离变化而呈平方关系。

(3)飞跃星空代码分析

#pragma comment(lib,"GLTools.lib")

#include <GLTools.h>    // OpenGL toolkit
#include <GLFrustum.h>
#include <StopWatch.h>
#include <math.h>
#include <stdlib.h>
#include <GL/glut.h>

//定义星星的数量
#define NUM_STARS 10000

GLFrustum           viewFrustum;
GLBatch             starsBatch;

GLuint  starFieldShader;    // The point sprite shader
GLint   locMVP;             // The location of the ModelViewProjection matrix uniform
GLint   locTimeStamp;       // The location of the time stamp
GLint   locTexture;         // The location of the  texture uniform

GLuint  starTexture;        // The star texture texture object


                            // Load a TGA as a 2D Texture. Completely initialize the state
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
    GLbyte *pBits;
    int nWidth, nHeight, nComponents;
    GLenum eFormat;

    // Read the texture bits
    pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, 
你可以在`<van-sidebar>`标签上添加`@change`事件监听器来实现索引切换时更新右侧布局的功能。具体实现如下: 1. 在`data`中定义需要切换的数据,以及当前选中的索引值: ```javascript data() { return { activeKey: 0, // 当前选中的索引值 racketList: [ // 不同索引对应的数据 { id: 1, name: '新手球拍', desc: '适合初学者使用的球拍' }, { id: 2, name: '进阶球拍', desc: '适合有一定基础的球员使用的球拍' }, { id: 3, name: '高级球拍', desc: '适合专业球员使用的球拍' } ], currentRacket: {} // 当前选中的球拍数据 } } ``` 2. 在模板中,使用`<van-sidebar-item>`标签渲染侧边栏,并绑定`activeKey`作为选中的索引值: ```html <van-sidebar v-model="activeKey" fixed="false"> <van-sidebar-item title="新手球拍" /> <van-sidebar-item title="进阶球拍" /> <van-sidebar-item title="高级球拍" /> </van-sidebar> ``` 3. 在模板中,使用`<van-card>`标签渲染右侧的布局,并根据当前选中的索引值显示对应的数据: ```html <van-card> <div class="card-content">{{ currentRacket.name }}</div> <div class="card-content">{{ currentRacket.desc }}</div> </van-card> ``` 4. 在`<script>`标签中,定义`onChange`方法来更新选中的索引值,并根据索引值更新右侧的数据: ```javascript methods: { onChange(index) { this.activeKey = index; // 更新选中的索引值 this.currentRacket = this.racketList[index]; // 更新右侧的数据 } } ``` 5. 在`<van-sidebar>`标签上添加`@change`事件监听器,将事件绑定到`onChange`方法上: ```html <van-sidebar v-model="activeKey" fixed="false" @change="onChange"> <van-sidebar-item title="新手球拍" /> <van-sidebar-item title="进阶球拍" /> <van-sidebar-item title="高级球拍" /> </van-sidebar> ``` 这样,当用户击侧边栏的不同项时,就会触发`@change`事件,从而更新选中的索引值和右侧的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值