当前位置:网站首页>OpenGL学习日记2——着色器
OpenGL学习日记2——着色器
2022-07-26 14:44:00 【herb.dr】
学习视频链接
目录
一、封装代码读取shader
1.1 编码使用 UTF8

1.2 头文件和对象

注释掉相关的内容

1.3 使用对象操作着色器

#include "openglwidget.h"
#include <QDebug>
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
// 创建VBO和VAO对象,并赋予ID
unsigned int VAO, VBO;
// unsigned int shaderProgram;
const char* vertexShaderScource =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\n\0";
const char* fragmentShaderScource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
OpenGLWidget::OpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
}
OpenGLWidget::~OpenGLWidget()
{
makeCurrent();
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &VAO);
//glDeleteProgram(shaderProgram);
doneCurrent();
}
void OpenGLWidget::drawShape(OpenGLWidget::Shape shape)
{
m_shape = shape;
update();
}
void OpenGLWidget::setWireframe(bool wireframe)
{
makeCurrent();
if(wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
update();
doneCurrent();
}
// 初始化的槽函数
// 在第一次调用paintGL()或resizeGL()之前调用一次,然后在小部件被分配新的QGLContext时调用一次
void OpenGLWidget::initializeGL()
{
initializeOpenGLFunctions();
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// 绑定VBO和VAO对象
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// 当前绑定到target的缓冲区对象创建一个新的数据存储
// 如果data不是NULL,则使用来自此指针的数据初始化数据存储
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 告知显卡如何解析缓冲里的属性值
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
// 开启VAO管理的第一个属性值
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
/*unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderScource, NULL);
glCompileShader(vertexShader);
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderScource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();*/
/*glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);*/
bool success;
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderScource);
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderScource);
success = shaderProgram.link();
if(success)
qDebug() << "ERR:" << shaderProgram.log();
/*glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);*/
}
void OpenGLWidget::resizeGL(int w, int h)
{
}
void OpenGLWidget::paintGL()
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
switch (m_shape) {
case Triangle:
shaderProgram.bind();
//glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
break;
default:
break;
}
}
1.4 新建着色器



着色器可以混用

运行结果没问题

二、着色器
2.1 一个 shader 程序的典型结构
对于顶点着色器,输入变量为 顶点属性 (vertex attribute)
#version version_number
in type in_variable_name ;
in type in_variable_name ;
out type out_variable name ;
uniform type uniform_name ;
void main ( )
{
// process input(s) and do some weird graphics stuff ...
// output processed stuff to output variable
out_variable_name = weird_stuff_we_processed;
}
2.2 顶点数量
我们能声明的顶点属性数量是有上限的,可以通过下面的代码获取:
nt nrAttributes;
glGetIntegerv(GL_MAX_VERTEX ATTRIBS, &nrAttributes) ;
OpenGL 确保至少有 16 个包含 4 分量的顶点属性可用,但是有些硬件或许允许更多的顶点属性
2.3 类型
1、GLSL 中包含 C 等其它语言大部分的默认基础数据类型:
int、float、double、uint 和 bool
2、GLSL 也有两种容器类型:
(1) 向量(Vector)
vecn: the default vector of n floats
bvecn: a vector of n booleans
ivecn: a vector of n integers
uvecn: a vector of n unsigned integers
dvecn: a vector of n double components
(2) 矩阵 (Matrix)
3、重组
向量允许一些有趣而灵活的分量选择方式,叫做重组 (Swizzling):
vec2 vect = vec2(0.5, 0.7);
vec4 result = vec4(vect, 0.0, 0.0);
vec4 otherResult = vec4(result.xyz, 1.0);
2.4 输入输出
在发送方着色器中声明一个输出
在接收方着色器中声明一个类似的输入
当类型和名字都一致,OpenGL 将把变量链接到一起 (在链接程序对象时完成)

2.5 代码
1、输入、输出


2、其他语法

还可以 .xxz 之类的
2.6 layout(location = ...)
顶点着色器接收的是一种特殊形式的输入,否则就会效率低下
从顶点数据中直接接收输入。为了定义顶点数据该如何管理,我们使用 location 这一元数据(mietadata) 指定输入变量,这样我们才可以在 CPU 上配置顶点属性。例如: layout (location = 0)。layout 这个的标识,使得我们能把它链接到顶点数据。
可以忽略 layout(location = 0) 标识符,通过在 OpenGL 代码中使用 glGetAttribLocation 查询属性位置值 (Location),或是 glBindAttribLocation 属性位置值 (Location),但是推荐在着色器中设置它们,这样会更容易理解而且节省你 (和OpenGL) 的工作量。
下图中从 0 开始存数据,从 2 开始读数据,程序会报错


现在我们获取到 shader 里面读取数据是从 2 开始,所以我们存放数据也是从 2 开始,这样就能顺利的运行程序了

边栏推荐
- C# NanUI 相关功能整合
- Siamrpn: recommended regional network and twin network
- What is the transport layer protocol tcp/udp???
- llcc68广播唤醒简单说明
- 14. Bridge based active domain adaptation for aspect term extraction reading notes
- JS analog clock with text label
- Cve-2022-33891 vulnerability recurrence
- C nanui related function integration
- 次轮Okaleido Tiger即将登录Binance NFT,引发社区热议
- Summary and analysis of image level weakly supervised image semantic segmentation
猜你喜欢

Canvas laser JS special effect code

C# Winfrom 常用功能整合

Okaleido tiger is about to log in to binance NFT in the second round, which has aroused heated discussion in the community

Character function and string function and memory function

堆叠降噪自动编码器 Stacked Denoising Auto Encoder(SDAE)

次轮Okaleido Tiger即将登录Binance NFT,引发社区热议

Embedded development: skills of debugging embedded software

【文件上传漏洞-06】分布式配置文件攻击实验—以upload-labs-4为例

下一代视觉Transformer:解锁CNN和Transformer正确结合方法

AMB | 迈向可持续农业:根际微生物工程
随机推荐
Network pictures are transferred locally, causing the kernel to exit
如何查询外文文献?
Simple implementation of pytorch
Postman environment variable setting code storage
CAS based SSO single point server configuration
C nanui related function integration
堆叠降噪自动编码器 Stacked Denoising Auto Encoder(SDAE)
生泰尔科技IPO被终止:曾拟募资5.6亿 启明与济峰资本是股东
最详细的专利申请教程,教你如何申请专利
中值滤波器
Siamrpn: recommended regional network and twin network
华为应用已经调用了checkAppUpdate接口,为什么应用内不提示版本更新
自编码器 AE(AutoEncoder)程序
31. Opinion based relational pivoting forcross domain aspect term extraction reading notes
Matlab solution of [analysis of variance]
How to get 5L water in a full 10L container, 7L or 4L empty container
Use of delve for go development and debugging
PyTorch的简单实现
一个满的10L容器,7L、4L空的容器,如何得到5L的水
Tips for unity transparent channel
https://www.bilibili.com/video/BV1UL411W71w?p=12&vd_source=0471cde1c644648fafd07b54e303c905