1.頂點着色器(Vertex Shader)
頂點着色器:幾個可編程着色器中的一個。
OpenGL用GLSL編寫着色器,GLSL看起來很像C語言。
#version 330 core
layout (location = 0) int vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0)
}
使用in 關鍵字,在頂點着色器中聲明所有的輸入頂點屬性。GLSL有一個向量數據類型,包含1到4個float分量。由於每個頂點都有一個3D座標,我們就創建一個vec3輸入變量aPos。
爲了設置頂點着色器的輸出,我們必須把位置數據賦值給預定義的gl_Position,它在幕後的vec4.
在main函數最後,我們將gl_Position設置的值會成爲該頂點着色器的輸出
編譯頂點着色器:
(1)創建一個着色器對象,用ID引用,用glCreateShader創建這個着色器
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
我們創建的是一個頂點着色器,傳遞的參數是GL_VERTEX_SHADER
(2)把這個着色器的源碼附加到着色器對象上
glShaderSource(vertexShader, 1, &vertexShader, NULL);
glCompileShader(vertexShader);
原型:
void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length);
第一個參數:要編譯的着色器對象
第二個參數:指定傳遞的源碼字符串數量
第三個參數:指定指向包含要加載到着色器中的源代碼的字符串的指針數組
第四個參數:指定字符串長度數組
原型:void glCompileShader(GLuint shader);
指定shader對象去編譯
2.片段着色器(Fragment Shader)
片段着色器:用於計算像素最後的顏色輸出
在計算機圖形中,顏色被表示爲有4個元素的數據,RGBA,當在OpenGL或者GLSL中定義一個顏色,我們把顏色每個分量的強度設置在0.0到1.0之間
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f)
}
片段着色器只需要一個輸出變量,這個變量是一個4分向量,表示的是最終的輸出顏色,將其計算出,可以用out關鍵字聲明輸出變量
編譯片段着色器:
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
3.着色器程序
着色器程序:多個着色器合併之後並最終鏈接完成的版本
我們要使用編譯的着色器,我們必須把它們鏈接爲一個着色器程序對象,然後再渲染對象的時候激活這個着色器程序
當鏈接着色器至一個程序的時候,它會把每個着色器的輸出鏈接到下個着色器的輸入。
(1)創建一個程序對象
usigned int shaderProgram;
shaderProgram = glCreateProgram();
(2)glCreateProgram函數創建一個程序,並返回該程序的ID引用,需要把之前編譯的着色器附加到程序對象,然後用glLinkProgram鏈接,得到的結果就是一個對象,可以調用glUseProgram函數
gkAttachShader(shaderProgram, vertexShader);
gkAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
(3)着色器鏈接到程序對象後,刪除着色器
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader)
應用:
#include <GL/glew.h>
#include<gl\glut.h>
#include<iostream>
void MyInit();
void reshape(int w, int h);
void display();
GLuint vboId;
GLuint vaoId;
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(512, 512);
glutCreateWindow("SHADER_RECTANGLE");
glewInit();
MyInit();
glutReshapeFunc(&reshape);
glutDisplayFunc(&display);
glutMainLoop();
return 0;
}
void MyInit()
{
glClearColor(0.0,0.0, 0.0,0.0);
const GLfloat vertices[] = {
-0.5f,-0.5f,0.0f,1.0f,
0.5f,-0.5f,0.0f,1.0f,
0.5f,0.5f,0.0f,1.0f,
-0.5f,0.5f,0.0f,1.0f,
};
//創建VAO對象
glGenVertexArrays(1, &vaoId);
glBindVertexArray(vaoId);
//創建VBO對象
glGenBuffers(1, &vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
//傳入VBO數據
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//解除VBO綁定
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void reshape(int w, int h)
{
glViewport(0, 0,(GLsizei)w, (GLsizei)h);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
const char* vertex_shader =
"#version 330\n"
"in vec3 aPos;"
"void main() {"
" gl_Position = vec4(aPos, 1.0);"
"}";
const char* fragment_shader =
"#version 330\n"
"out vec4 FragColor;"
"void main() {"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);"
"}";
//頂點着色器
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertex_shader, NULL);
glCompileShader(vertexShader);
//片段着色器
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragment_shader, NULL);
glCompileShader(fragmentShader);
//着色器程序
GLuint shader_programme = glCreateProgram();
//鏈接着色器
glAttachShader(shader_programme, fragmentShader);
glAttachShader(shader_programme, vertexShader);
glLinkProgram(shader_programme);
glUseProgram(shader_programme);
//刪除着色器
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
//綁定VBO
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glEnableVertexAttribArray(0);
//解釋頂點數據方式
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
//繪製模型
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glutSwapBuffers();
}
效果: