OpenGL学习22——GLSL

2021-07-24  本文已影响0人  蓬篙人

1. 顶点着色器变量

glEnable(GL_PROGRAM_POINT_SIZE);
void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
    gl_PointSize = gl_Position.z;
}

2. 片元着色器变量

void main()
{
    if(gl_FragCoord.x < 400)
        FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    else
        FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
片元位置渲染
#version 330 core
out vec4 FragColor;

in vec2 TexCoords;

uniform sampler2D frontTexture;
uniform sampler2D backTexture;

void main()
{
    if(gl_FrontFacing)
        FragColor = texture(frontTexture, TexCoords);
    else
        FragColor = texture(backTexture, TexCoords);
}
片元面向渲染
gl_FragDepth = 0.0;
layout (depth_<condition>) out float gl_FragDepth;
条件值 描述
any 默认值,禁用早期深度测试,丧失大部分性能。
greater 你只能让深度值大于gl_FragCoord.z
less 你只能让深度值小于gl_FragCoord.z
unchanged 你只能给gl_FragDepthgl_FragCoord.z值。
// 注意这里的版本
#version 420 core
out vec4 FragColor;
layout (depth_greater) out float gl_FragDepth;

void main()
{
    FragColor = vec4(1.0);
    gl_FragDepth = gl_FragCoord.z + 0.1;
}

3. 接口模块(Interface blocks)

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out VS_OUT
{
    vec2 TexCoords;
} vs_out;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
    vs_out.TexCoords = aTexCoords;
}
#version 330 core
out vec4 FragColor;

in VS_OUT
{
    vec2 TexCoords;
} fs_in;

uniform sampler2D texture;

void main()
{
    FragColor = texture(texture, fs_in.TexCoords);
}

4. Uniform缓冲区对象

#version 330 core
layout (location = 0) in vec3 aPos;

layout (std140) uniform Matrices
{
    mat4 projection;
    met4 view;
};

uniform mat4 model;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
}

5. uniform模块布局

类型 布局规则
标量,如int或bool 每个标量的基本对齐为N
矢量 不是2N就是4N,这意味着vec3的基本对齐是4N
标量或矢量数组 每个元素的基本对齐与vec4相等
矩阵 以列矢量数组进行存储,每个矢量的基本对齐与vec4相等。
结构 根据前面的规则计算出元素大小的和,但补齐为vec4大小的倍数。
layout (std140) uniform ExampleBlock
{
                      // 基本对齐      // 对齐偏移量
    float value;      // 4            // 0
    vec3 vector;      // 16           // 16 (16的倍数:4->16)
    mat4 matrix;      // 16           // 32 (列0)
                      // 16           // 48 (列1)
                      // 16           // 64 (列2)
                      // 16           // 80 (列3)
    float values[3];  // 16           // 96 (values[0])
                      // 16           // 112 (values[1])
                      // 16           // 128 (values[2])
    bool boolean;     // 4            // 144
    int integer;      // 4            // 148
};

6. 使用uniform缓冲区

unsigned int uboExampleBlock;
glGenBuffers(1, &uboExampleBlock);
glBindBuffer(GL_UNIFORM_BUFFER, uboExampleBlock);
glBufferData(GL_UNIFORM_BUFFER, 152, NULL, GL_STATIC_DRAW);   // 分配152个字节
glBindBuffer(GL_UNIFORM_BUFFER, 0);
// 注意,对于每个着色器中的uniform模块我们都需要执行以下操作
unsigned int lights_index = glGetUniformBlockIndex(shaderA.ID, "Lights");
glUniformBlockBinding(shaderA.ID, lights_index, 2);
layout (std140, binding = 2) unfirom Lights { ... }
glBindBufferBase(GL_UNIFORM_BUFFER, 2, uboExampleBlock);

glBindBufferRange(GL_UNIFORM_BUFFER, 2, uboExampleBlock, 0, 152);
glBindBuffer(GL_UNIFORM_BUFFER, uboExampleBlock);
int b = true;   // GLSL中的bool定义为4个字节,因此保存为整数
// 参数值参考我们前面布局计算的例子
glBufferSubData(GL_UNIFORM_BUFFER, 144, 4, $b);
glBindBuffer(GL_UNIFORM_BUFFER, 0);

7. 一个简单的例子

从前面章节的代码我们知道,在渲染过程中我们经常需要使用投影、视和模型矩阵。这些矩阵中,只有模型矩阵经常需要改变。如果我们有多个着色器需要使用这些矩阵,那么我们最好使用uniform缓冲区对象。

#version 330 core
layout (location = 0) in vec3 aPos;

layout (std140) uniform Matrices
{
    mat4 projection;
    mat4 view;
};
uniform mat4 model;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
}
unsigned int red    = glGetUniformBlockIndex(shaderRed.ID,    "Matrices");
unsigned int green  = glGetUniformBlockIndex(shaderGreen.ID,  "Matrices");
unsigned int blue   = glGetUniformBlockIndex(shaderBlue.ID,   "Matrices");
unsigned int yellow = glGetUniformBlockIndex(shaderYellow.ID, "Matrices");

glUniformBlockBinding(shaderRed.ID,    red,    0);
glUniformBlockBinding(shaderGreen.ID,  green,  0);
glUniformBlockBinding(shaderBlue.ID,   blue,   0);
glUniformBlockBinding(shaderYellow.ID, yellow, 0);
// generate uniform buffer object and allocate memory
unsigned int uboMatrices;
glGenBuffers(1, &uboMatrices);
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), NULL, GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
// bind buffer to binding point 0
glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboMatrices, 0, 2 * sizeof(glm::mat4));
// store data into the buffer that link to uniform block
glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(projection));
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glm::mat4 view = camera.GetViewMatrix();
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(view));
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glBindVertexArray(objectVAO);
// red cube
redShader.use();
glm::mat4 model = glm::mat4(1.0f);
model = glm::scale(model, glm::vec3(0.6f));
model = glm::translate(model, cubePositions[0]);
redShader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
// green cube
greenShader.use();
model = glm::mat4(1.0f);
model = glm::scale(model, glm::vec3(0.6f));
model = glm::translate(model, cubePositions[1]);
greenShader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
// blue cube
blueShader.use();
model = glm::mat4(1.0f);
model = glm::scale(model, glm::vec3(0.6f));
model = glm::translate(model, cubePositions[2]);
blueShader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
// yellow cube
yellowShader.use();
model = glm::mat4(1.0f);
model = glm::scale(model, glm::vec3(0.6f));
model = glm::translate(model, cubePositions[3]);
yellowShader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
上一篇下一篇

猜你喜欢

热点阅读