第二十一课,几何着色器(基础篇)

2023-11-15

几何着色器的作用

输入

输入类型

从顶点着色器接收下列任何一个图元值:

类型 数组大小
points:绘制GL_POINTS图元时。 1
lines:绘制GL_LINES或GL_LINE_STRIP时 2
lines_adjacency:GL_LINES_ADJACENCY或GL_LINE_STRIP_ADJACENCY 4
triangles:GL_TRIANGLES、GL_TRIANGLE_STRIP或GL_TRIANGLE_FAN 3
triangles_adjacency:GL_TRIANGLES_ADJACENCY或GL_TRIANGLE_STRIP_ADJACENCY 6

补充:lines_adjacency 图元装配的时候每次总是4个顶点的数量a,b,c,d。实际上真正绘制的点是b和c,其他的点是提供邻接关系的点。
triangles_adjacency作为图元输入时,每个图元由6个顶点组成,opengl可以通过绘制命令传入GL_TRIANGLES_ADJACENCY, GL_TRIANGLES_STRIP_ADJACENCY来控制,为了说明怎么工作的盗两张图
在这里插入图片描述
在这里插入图片描述


作者:纳尼情况zhuzhu
链接:https://www.jianshu.com/p/8bca19bc5ade
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

具体怎么样,以后再补充QwQ。

输入布局修饰符

这需要在in关键字前声明一个布局修饰符(Layout Qualifier)

layout (points) in;

point表示输入的类型为顶点。

输出

输出类型

然后输出下面的图元类型。

  • points ------------------------------点
  • line_strip --------------------------线
  • triangle_strip----------------------三角形
输出布局修饰符

几何着色器同时希望我们设置一个它最大能够输出的顶点数量(如果你超过了这个值,OpenGL将不会绘制多出的顶点),这个也可以在out关键字的布局修饰符中设置。

layout (line_strip, max_vertices = 2) out;

表示输出为line strip(线条),最大顶点数为2(即只有一条线段)。

作用

它接受一个图元(例如point,line)作为输入,以这个点/线为初始数据,创建较为复杂的图元。

几何着色器的构建

输入布局

layout (points) in;

输入数据块

GeometryShader

在GeometryShader中接收输入块,该块是一个数组,接收所有在vertexShader中输出的VS_OUT块。

in VS_OUT {
    vec3 color;
} gs_in[];

color可以为数组,为几何着色器提供图元不同顶点的颜色输出。

vertexShader

在vertexShader有

out VS_OUT {
    vec3 color;
} vs_out;
vs_out.color = aColor;

内建变量

即不会写出来,但存在这样的变量。

in gl_Vertex
{
    vec4  gl_Position;
    float gl_PointSize;
    float gl_ClipDistance[];
} gl_in[];

这里可以看出,几何着色器的输入是一个图元的所有顶点。

修改原数据,并添加到输出的顶点集中

gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0); 
fColor = gs_in[0].color;//
EmitVertex();//提交该顶点到图元

此处使用第一个顶点的位置确定了当前顶点的位置,以及使用自定义接口块确定了当前顶点的颜色,并将这个顶点提交到图元。

注意:gl_in[i].gl_Position为顶点着色器输出几何着色器的第i个顶点的位置
gl_PositionEmitVertex()提交到图元的顶点。

提交输出集

 EndPrimitive();

将当前存储的图元提交到fragment片元着色器中,一个图元的最大顶点数在输出布局修饰符中指定。

输出布局

layout (triangle_strip, max_vertices = 5) out;

几何着色器的使用

创建着色器程序

Shader shader("9.1.geometry_shader.vs", "9.1.geometry_shader.fs", "9.1.geometry_shader.gs");

这显然用之前着色器类的构造函数是不行的。

LearnOpenGL网站代码方法
Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr)
    {
        // 1. retrieve the vertex/fragment source code from filePath
        std::string vertexCode;
        std::string fragmentCode;
        std::string geometryCode;
        std::ifstream vShaderFile;
        std::ifstream fShaderFile;
        std::ifstream gShaderFile;
        // ensure ifstream objects can throw exceptions:
        vShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
        fShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
        gShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
        try 
        {
            // open files
            vShaderFile.open(vertexPath);
            fShaderFile.open(fragmentPath);
            std::stringstream vShaderStream, fShaderStream;
            // read file's buffer contents into streams
            vShaderStream << vShaderFile.rdbuf();
            fShaderStream << fShaderFile.rdbuf();		
            // close file handlers
            vShaderFile.close();
            fShaderFile.close();
            // convert stream into string
            vertexCode = vShaderStream.str();
            fragmentCode = fShaderStream.str();			
            // if geometry shader path is present, also load a geometry shader
            if(geometryPath != nullptr)
            {
                gShaderFile.open(geometryPath);
                std::stringstream gShaderStream;
                gShaderStream << gShaderFile.rdbuf();
                gShaderFile.close();
                geometryCode = gShaderStream.str();
            }
        }
        catch (std::ifstream::failure& e)
        {
            std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
        }
        const char* vShaderCode = vertexCode.c_str();
        const char * fShaderCode = fragmentCode.c_str();
        // 2. compile shaders
        unsigned int vertex, fragment;
        // vertex shader
        vertex = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertex, 1, &vShaderCode, NULL);
        glCompileShader(vertex);
        checkCompileErrors(vertex, "VERTEX");
        // fragment Shader
        fragment = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragment, 1, &fShaderCode, NULL);
        glCompileShader(fragment);
        checkCompileErrors(fragment, "FRAGMENT");
        // if geometry shader is given, compile geometry shader
        unsigned int geometry;
        if(geometryPath != nullptr)
        {
            const char * gShaderCode = geometryCode.c_str();
            geometry = glCreateShader(GL_GEOMETRY_SHADER);
            glShaderSource(geometry, 1, &gShaderCode, NULL);
            glCompileShader(geometry);
            checkCompileErrors(geometry, "GEOMETRY");
        }
        // shader Program
        ID = glCreateProgram();
        glAttachShader(ID, vertex);
        glAttachShader(ID, fragment);
        if(geometryPath != nullptr)
            glAttachShader(ID, geometry);
        glLinkProgram(ID);
        checkCompileErrors(ID, "PROGRAM");
        // delete the shaders as they're linked into our program now and no longer necessery
        glDeleteShader(vertex);
        glDeleteShader(fragment);
        if(geometryPath != nullptr)
            glDeleteShader(geometry);

    }

private:
    // utility function for checking shader compilation/linking errors.
    // ------------------------------------------------------------------------
    void checkCompileErrors(GLuint shader, std::string type)
    {
        GLint success;
        GLchar infoLog[1024];
        if(type != "PROGRAM")
        {
            glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
            if(!success)
            {
                glGetShaderInfoLog(shader, 1024, NULL, infoLog);
                std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
            }
        }
        else
        {
            glGetProgramiv(shader, GL_LINK_STATUS, &success);
            if(!success)
            {
                glGetProgramInfoLog(shader, 1024, NULL, infoLog);
                std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
            }
        }
    }
};

传入数据

与之前一样

float points[] = {
    -0.5f,  0.5f, // 左上
     0.5f,  0.5f, // 右上
     0.5f, -0.5f, // 右下
    -0.5f, -0.5f  // 左下
};

unsigned int VBO, VAO;
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), &points, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(2 * sizeof(float)));
glBindVertexArray(0);
 	shader.use();
    glBindVertexArray(VAO);
    glDrawArrays(GL_POINTS, 0, 4);

实验结果

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第二十一课,几何着色器(基础篇) 的相关文章

  • 不明确的 OpenGL 默认相机位置

    在我的Opengl程序中 在我应用透视投影矩阵之前 每当我绘制一些对象时 我都会在世界坐标系的原点处绘制它 但是几乎所有Opengl教程都指出相机 我的投影视图 位于原点朝向正 z 轴 这取决于您稍后如何处理投影矩阵中的 z 值 但是如果这
  • 纹理的内部格式

    看下面的OpenGL函数 void glTexImage2D GLenum target GLint level GLint internalFormat GLsizei width GLsizei height GLint border
  • 如何从横滚、俯仰和偏航获取相机向上矢量?

    我需要从滚动角 俯仰角和偏航角 以度为单位 获取相机的向上矢量 以获得正确的外观 我已经尝试了几个小时不同的事情 但没有运气 这里的任何帮助将不胜感激 横滚 俯仰和偏航定义 3 轴旋转 从这些角度 您可以构建一个 3x3 变换矩阵来表达该旋
  • 为什么 OpenGL 有远裁剪平面,以及使用什么惯用法来处理这个问题?

    我一直在学习 OpenGL 持续困扰我的一个话题是远裁剪平面 虽然我可以理解近剪裁平面和侧剪裁平面 它们永远不会产生任何实际效果 因为它们之外的对象无论如何都不会被渲染 背后的推理 但远剪裁平面似乎只是一个烦恼 由于 OpenGL 背后的人
  • 为什么 glClear 不清除我的屏幕?

    这是我编写的一个简单的 opengl 程序 我试图在绘制三角形之前清除屏幕 我在 init 函数中调用了 glClear 但是 它似乎无法清除屏幕 include
  • LibGDX纹理混合与OpenGL混合功能

    在 libGdx 中 我试图创建一个成形纹理 采用完全可见的矩形纹理并将其遮罩以获得成形纹理 如下所示 在这里我在矩形上测试它 但我想在任何形状上使用它 我调查过本教程 http www learnopengles com tag addi
  • 3D 空间中两个盒子之间的交集

    我想为我的图形引擎实现一个碰撞检测系统 我不知道这是否是常见的方法 但我的想法是将任何实体对象 如网格或相机 绑定在 3D 盒子内 这会给我比球体更准确的结果 这个盒子由八个顶点定义 x0 min vertices x off parsin
  • OpenGL中背景对象绘制在前景对象前面?

    为了测试目的 我们假设我画了 2 个茶壶glutSolidTeapot 像这样 glColor3f 1 0f 0 0f 0 0f Red teapot glutWireTeapot 1 0f glColor3f 0 0f 1 0f 0 0f
  • 渲染具有透明度的纹理时,OpenGL 不需要的像素

    我已经为这个问题苦苦挣扎了一段时间了 当我使用 OpenGL 渲染 2D 纹理 在无透明度和部分透明度之间的过渡上具有透明度值 时 我得到了一些烦人的灰色像素 我认为这是像素值插值的产物 关于如何改进这一点有什么想法吗 I m attach
  • 无法使用 vcglib 简化 3D 模型,断言“0”失败

    I used vcglib https github com cnr isti vclab vcglib简化 3D 模型文件 我使用了 master a8e87662 git 存储库 我运行示例 trimesh clustering htt
  • Windows下使用GLEW使用OpenGL扩展

    我一直在 Windows 上使用 OpenGL 扩展痛苦的方式 https stackoverflow com questions 14413 using opengl extensions on windows GLEW 是更简单的方法吗
  • 为什么我的 3D 绘图没有显示在 R Studio 绘图查看器中?

    我通常在 RStudio 版本 1 0 44 中查看绘图时没有问题 但是当我尝试查看使用 rgl 包创建的 3D 绘图时 我的 RStudio 绘图查看器中什么也没有出现 我能够毫无问题地绘制图 汽车 散点图 这是我正在使用的代码 inst
  • OpenGL:始终相同的颜色

    我正在 Windows 上编写一个程序 使用c opengl 2 1 and SDL我在顶点颜色方面遇到了一些问题 我在用着glColor3f设置每个顶点集的颜色 但它似乎不起作用 无论我选择什么颜色 我都会将每个顶点绘制为红色 我检查了传
  • 3D 透视投影的剪辑矩阵

    我正在尝试创建一个简单的 3D 图形引擎 并找到并使用了我在这里找到的方程 http en wikipedia org wiki 3D projection cite note 0 http en wikipedia org wiki 3D
  • 求截头棱锥体/截棱锥体横截面的边长

    如何找到横截面的边长 如图所示 下图 横截面 红色 截头锥体 截棱锥体 我知道顶部和底部的边长 以及底部的高度 截锥体和到横截面的距离 此外我还知道 顶部和底部底座平行 并且顶部和底部的中心 底部底座直接位于彼此之上 比例是线性的 因此只需
  • 渲染缓冲区大于窗口大小 - OpenGL

    我正在尝试绘制大于屏幕尺寸 即 320x480 的渲染缓冲区 512x512 执行 glReadPixels 后 图像看起来是正确的 除非图像的尺寸超过了屏幕尺寸 在本例中 超过了水平 320 和垂直 480 是什么原因导致这种异常现象呢
  • 纹理采样:根据LOD值计算BIAS值

    GL ES 2 0 中的功能纹理2DLod在片段着色器中不可用 我需要移植 GLSL 着色器 在 GL ES 2 0 中我只能使用二维纹理 sampler2D 采样器 vec2 坐标 浮点数bias 告诉我如何计算 a 的值bias相当于已
  • 如何在多采样纹理上渲染帧缓冲区对象?

    我目前有一个使用多个通道的渲染引擎 其中图像的各个部分在纹理上渲染 然后使用着色器进行组合 它有效 现在我想激活多重采样 我在这里读到 http www opengl org wiki Framebuffer Object Examples
  • 计算任意网格的平面 UV 坐标

    我有从二维形状生成三角形网格的代码 因为在大多数情况下 这些形状在表面上的顶点分布不均匀 所以我在生成 UV 时遇到了问题 这样就不会导致纹理扭曲 任何人都可以推荐一些讨论平面网格上 UV 计算技术的文章 书籍 代码示例吗 谢谢 好的 让我
  • WGL:没有双缓冲 + 多重采样 = 失败?

    我通常使用创建像素格式wglChoosePixelFormatARB 与这些论点 除其他外 WGL DOUBLE BUFFER ARB GL TRUE WGL SAMPLE BUFFERS ARB GL TRUE WGL SAMPLES A

随机推荐

  • 发送ARP数据包

    发送ARP数据包 ARP 地址解析协议 即ARP Address Resolution Protocol 是根据IP地址获取物理地址的一个TCP IP协议 主机发 送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机 并接收返回消息
  • 服务器虚拟化技术

    一 服务器虚拟化概述 1 服务器虚拟化简介 在一台物理服务器上运行多个虚拟服务器称为 服务器虚拟化 在服务器虚拟化中 专用虚拟化软件将物理服务器上的处理器存储器之类的资源划分为多个资源 并将其分配给虚拟服务器 由于可以在一台物理服务器上聚合
  • Python爬虫 XPath解析出乱码 解决方法

    请求后加上编码 resp requests get url headers headers resp encoding GBK
  • Springboot操作Elasticsearch——聚合分组与排序

    这两天项目中需要从es中查询数据 根据某个字段进行分组 求其最大 最小 平均值 并按最大值进行排序 springboot的版本号 2 0 6 RELEASE Elasticsearch的版本号 5 6 3 主要代码记录下 BoolQuery
  • 拆解开源项目Blender

    计划把Blender项目拆解出来 如果把Blender项目比作一辆汽车 那拆解的任务就是把它的发动机 轮胎 支架等不同的模块单独出来并能独自运行 不知道以前有没有人这样干过 在其他项目上 这样拆解的好处是可以更好地研究它的工作原理 并将这些
  • AFNetWorking出现code=-1016错误解决办法

    AFNetWorking的JSON解析默认库是使用的AFJSONRequestOperation模式 只支持text json application json text javascript 所以如果出现code 1016错误则说明当前的
  • 告别2021,迎接2022

    2021相对有点忙有点累 一直想记录一下 但是实在是在惰性趋势下 歇息了一个月 才正常提笔微记 最近思绪也比较忙 提笔规划也是有点凌乱 2021年在新单位的第二年 开始结交朋友 受朋友们的影响 开始准备考研 软考 幸运的是 也都坚持下来了
  • adb将Apk内置到系统中(system/priv-app)

    有时候我们在Android 系统内置自己的应用 在测试时 Android Studio 默认的安装方式是将我们开发的应用作为普通应用安装到系统中的 本文提供一种方式 在开发过程中 将apk内置到系统中 而不需要系统源代码 adb 将apk内
  • java新建一个窗口_Java实例:使用JFram创建一个简单的窗口

    一个图形用户界面以一个top level container开始 它为其他的界面组件提供了一个 家 指定应用程序的总体感觉 在本教程中 向你介绍JFrame类 它将用于给一个Java应用程序创建一个简单的top level窗口 打开你的编辑
  • UI操作 解决方案

    1 include
  • 中断、信号、系统调用

    1 中断的分类 中断程序的方法可以分为硬件中断和软件中断 硬件中断是硬件自动触发的 包括中断和异常 比如 中断 通过中断控制器给CPU的INTR引脚发送信号 如按下键盘 会给CPU一个0x21中断号 异常 CPU执行某条指令发生异常 会自己
  • tr td分合并单元格

    table border 1 width 200 tr td ss td tr tr td width 25 td td width 25 td tr table
  • Spark性能优化:数据倾斜调优

    前言 继 Spark性能优化 开发调优篇 和 Spark性能优化 资源调优篇 讲解了每个Spark开发人员都必须熟知的开发调优与资源调优之后 本文作为 Spark性能优化指南 的高级篇 将深入分析数据倾斜调优与shuffle调优 以解决更加
  • 设计补偿器网络以改善开关频率响应

    直流开关电压转换器 或 开关调节器 控制回路的特点是频率响应 频率响应影响开关调节器的反应时间对瞬态变化 精度和稳定性的影响 并在输入电压 负载和工作周期变化的情况下 如何保持设定的电压输出 工程师可以通过增加补偿器网络来改善开关调节器的频
  • Linux在云服务器上安装JDK

    官网地址下载 Java Downloads Oracle 将下载好的jdk通过Xftp传输到服务器上去 创建一个文件夹用于区分 在home文件夹下创建一个属于自己的文件夹 将需要的文件传输过去 也可以直接在 usr local 下配置 cd
  • win7电脑最新版微信卡死问题的解决

    最近一段时间无论单位还是家里事情都比较多 导致没有时间学习和写文 排名蹭蹭地往下掉 刚好遇到一个win7版微信卡死的问题 在网上查了下 找到了win10相关的可以参考的解决办法 确实有效 在此介绍一下 一 问题现象 当最小化win7托盘的微
  • linux环境安装php fileinfo扩展

    linux环境安装php fileinfo扩展 windows环境安装扩展比较简单 只需要把dll拷贝到扩展目录 修改php ini中相应的扩展就好了 下面来介绍一下linux环境下的php扩展安装 以centos6 5和php7 1为例
  • C++ OpenCV制作九宫格拼图游戏

    学更好的别人 做更好的自己 微卡智享 本文长度为2498字 预计阅读7分钟 前言 上一篇 C OpenCV生成九宫格图像 介绍了如何将图片分割城九宫格 然后重新打乱了顺序显示出来 本篇就来说一下怎么制作一个九宫格的拼图游戏 项目的重新创建了
  • JAVA是什么意思

    JAVA的意思是计算机的编程语言 Java通过面向对象的编程语言 它不仅吸收了C 语言的优点 而且摒弃了C 中难于理解的多继承和指针的概念 具有简单性 功能强大 分布式 健壮性 安全性 平台独立与可移植性 多线程及动态性的特点 Java语言
  • 第二十一课,几何着色器(基础篇)

    几何着色器的作用 输入 输入类型 从顶点着色器接收下列任何一个图元值 类型 数组大小 points 绘制GL POINTS图元时 1 lines 绘制GL LINES或GL LINE STRIP时 2 lines adjacency GL