第五章 视口变换、剪切与反馈

第五章 视口变换、剪切与反馈

观察视图

OpenGL的坐标系统:

在这里插入图片描述

OpenGL变换

设置远近平面

void glDepthRange(GLclampd near, GLclampd far);
void glDepthRangef(GLclampf near, GLclampd far);

近平面和远平面的值也就是深度缓存中所保存的最小值和最大值。默认情况下分别取0.0和1.0,所设置的范围是[0, 1]之间的。

设置绘制区域

void glViewport(GLint x, GLint y, GLint width, GLint height);

设置窗口中的渲染范围。

用户剪切

可以使用着色器内置变量gl_clipDistance来设置用户裁剪平面,需要自行设置它的内容,它的值会经过插值设置给顶点之间的片元。

#version 330 core
uniform vec4 Plane;  // 平面方程 Ax + By + Cz + D = 0的系数
in vec4 Vertex;

float gl_clipDistance[1];

void main()
{
    gl_clipDistance[0] = dot(Vertex, Plane);
}

这个变量的含义是顶点距离平面的距离,0表示在平面上,整数表示在平面内测,负值表示在平面外侧,OpenGL会抛弃距离小于0的片元。
所有使用gl_clipDistance的着色器必须将其声明为同样大小。
在使用之前需要使用glEnable(GL_CLIP_PLANE0)来激活指定剪切平面。

transform feedback

transform feedback是图元装配和光栅化之前的步骤,可以将即将装配为图元的顶点部分或者全部传递到缓存对象中。

创建transform feedback对象

transform feedback状态保存在transform feedback对象中,状态包括记录顶点数据的缓存对象,用于标识缓存对象充满程度的计数器,以及用于标识transform feedback当前是否启用的状态量。

void glGenTransformFeedbacks(GLsizei n, GLuint * ids);

绑定transform feedback

void glBindTransformFeedback(GLenum target, GLuint id);

target必须是GL_TRANSFORM_FEEDBACK。

id是否是transform feedback对象名

void glIsTransformFeedback(GLuint id);

删除transform feedback对象

void glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids);

绑定缓存对象到transform feedback缓存绑定点

void glBindBufferBase(GLenum target, GLuint index, GLuint buffer);

将名为buffer的缓存对象绑定到目标target的某个绑定点上,其索引通过index设置,同时绑定到target所设置的一般缓存绑定点上。

绑定缓存的一部分

void glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);

指定记录变量

void glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar** varyings, GLenum bufferMode)

program指定所用程序
count, varings指定输出变量名
bufferMode标记不活的变量是如何分配的。GL_INTERLEAVED_ATTRIBS表示所有变量是一个接着一个记录在当前的transform feedback的第一个绑定点的缓存对象里;GL_SEPARATE_ATTRIBS表示每个变量都会记录到一个单独的缓存对象中。

不同stream的输出不能被保存在同一个buffer中。
需要在链接程序之前调用才能生效。

GL_INTERLEAVED_ATTRIBS存储方式:

在这里插入图片描述

GL_SEPARATE_ATTRIBS存储方式:

在这里插入图片描述

如果需要自定义变量在缓存中的存储方式,可以使用gl_SkipComponents{1,2,3,4}和gl_NextBuffer,如果遇到任何一个gl_SkipComponents变量,会在transform feedback缓存中留出一个指定数量的空隙,只有在GL_INTERLEAVED_ATTRIBS时才能使用。

如果OpenGL遇到gl_NextBuffer那么它会将变量传递到当前绑定的下一个transform feedback缓存中。如果在GL_SEPARATE_ATTRIBS时我们遇到gl_NextBuffer或者在GL_INTERLEAVED_ATTRIBS遇到两个或者多个gl_NextBuffer,那么他将会直接跳过当前绑定点,并且在当前绑定的缓存中不会记录任何数据

static const char* const vars[] = 
{
    "foo", "gl_SkipComponents1", "bar", "gl_SkipComponents2",
    "gl_NextBuffer",
    "gl_SkipComponents4", "baz", "gl_SkipComponents2",
    "gl_NextBuffer",
    "gl_NextBuffer",
    "iron", "gl_SkipComponents3", "copper"
};

glTransformFeedvackVaryings(prog, sizeof(vars) / sizeof(vars[0]), varyings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(prog);

获得的存储结果:

在这里插入图片描述

启动transform feedback

void glBeginTransformFeedback(GLenum primitiveMode);

设置transform feedback准备记录的图元类型。只能用GL_POINTS、GL_LINES和GL_TRIANGLES,之后的绘制命令使用的图元类型必须与它相符合,或者几何着色器的输出类型必须与primitiveMode相符。

在这里插入图片描述

暂停transform feedback

void glPauseTransformFeedback(void);

tranform feed暂停之后,仍然是启动状态,但是不会像缓存中记录任何数据。
暂停模式下的限制:

  • 当前绑定的transform feedback对象不可改变
  • 不允许其他缓存绑定到GL_TRANSFORM_FEEDBACK_BUFFER的绑定点
  • 当前的程序对象不能改变。

如果当前绑定的transform feedback没有启动或者已经处于暂停状态,那么暂停会产生一个错误。

重启transform feedback

void glResumeTransformFeedback()

完成停止transform feedback渲染

void glEndTransformFeedback(void);

对于double类型的值,需要特别处理:

  • 每一个双精度类型值,都需要8个字节。
  • 包含双进度类型值的结构必须以8个字节对齐

例子:

out DataBlock
{
    float var1;
    dvec2 someDoubles;
    float var3;
};

const char *varyings[] =
{
    "DataBlock.var1",
    "gl_SkipComponents1",     //Padding the next component to 8-byte alignment.
    "DataBlock.someDoubles",
    "DataBlock.var3",
    "gl_SkipComponents1",     //Padding out the entire vertex structure to 8-byte alignment.
};

着色器内部指定

  • xfb_offset: 指定变量从当前顶点开始的位置偏移,单位是字节
  • xfb_buffer: 指定输出到的buffer索引
  • xfb_stride: 指定变量的长度,最小是4
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值